我正在使用Meteor和React-Router,我有以下代码:
Routes.jsx:
Meteor.startup(() => {
render(
<Router history={browserHistory}>
<Route path='/' component={App}>
<IndexRoute components={{ main: SelectTable, sidebar: MenuBar }} />
<Route path='/DisplayTable/:tableId'
components={{ main: DisplayTable, sidebar: MenuBar }} />
</Route>
<Route path='*' component={NotFound} />
</Router>,
document.getElementById('react-root'));
});
App.jsx:
export class App extends Component {
render() {
// if there's only one child logic here, irrelevant
return (
<div className='container'>
<div className="Main">
{this.props.main}
</div>
<div className="Sidebar">
{this.props.sidebar}
</div>
</div>);
}
}
我的 DisplayTable 组件侦听对数据库的Meteor订阅,并最终获取这些属性:
DisplayTable.propTypes = {
tableId: PropTypes.string.isRequired,
loading: PropTypes.bool.isRequired,
rows: PropTypes.array.isRequired,
cols: PropTypes.array.isRequired,
user: PropTypes.object,
};
我的 MenuBar 组件会显示:
<li><InsertRow tableId={this.props.params.tableId}/></li>
InsertRow 具有这些属性
InsertRow.propTypes = {
rows: PropTypes.array,
tableId: PropTypes.string,
};
其中InsertRow
和DisplayTable
的行属性完全相同。
如何将属性从主要组件传递到侧边栏,以便我可以将其从那里传递给组件?
React.cloneElement
的东西,虽然我真的无法绕过那个...... main
和sidebar
的所有属性,似乎找不到任何有用的内容...... 变通:
tableId
,但这似乎过于愚蠢,因为这两个组件实际上是在同一个路径中呈现。MenuBar
上创建一个假div,并在我显示表时使用jQuery替换它,但这似乎没有反应。(我没有使用反应路由器4.0,如果它与答案相关,使用3.0.5,最新版本的流星,虽然我猜这在这种情况下不相关)
编辑:我想我会在路径上方添加容器,所以我已经有了数据。虽然我会留下这个以防万一有更好的建议,但有点有意义。
答案 0 :(得分:1)
虽然可能有更好的方法,但我会在下面解释我最终做的事情:
<强> Routes.jsx 强>
Meteor.startup(() => {
render(
<Router history={browserHistory}>
<Route path='/' component={App}>
//... like before
<Route path='/DisplayTable' component={ Comp } >
<Route path='/DisplayTable/:tableId'
components={{ main: DisplayTable, sidebar: MenuBar }} />
</Route>
</Route>
<Route path='*' component={NotFound} />
</Router>,
document.getElementById('react-root'));
});
然后我添加了组件布局Comp
<强> Comp.jsx 强>
class Comp extends Component {
render() {
// this is the final html for our table
let displayTable = [];
let menuBar = [];
// while the data is loading, the html is a spinner
if (this.props.loading) {
displayTable.push(
<div key='table-container' className='table-container table-container-no-data'>
<div key='loading'>
<span>Loading data...</span>
<Spinner key='spinner' spinnerName='three-bounce' />
</div>
</div>);
} else {
// the Display Table properties
displayTable = React.Children.map(this.props.main, child => React.cloneElement(child, {
rows: this.props.rows,
cols: this.props.cols,
}));
// the Menu Bar properties
menuBar = React.Children.map(this.props.sidebar, child => React.cloneElement(child, {
rows: this.props.rows,
cols: this.props.cols,
}));
}
return (
<div className='container'>
<div className="content">
{displayTable}
</div>
<div className="menu">
{menuBar}
</div>
</div>);
}
}
Comp.propTypes = {
loading: PropTypes.bool.isRequired,
rows: PropTypes.array.isRequired,
cols: PropTypes.array.isRequired,
//... etc
};
/**
* A Meteor createContainer component which retrieves data from Meteor & Mongo
*/
export default createContainer((props) => {
// get the rows & cols by Meteor subscriptions here, as well as a loading to figure out when the subscription finished (this was originally in DisplayTable)
}
<强> DisplayTable.jsx 强>
DisplayTable.propTypes = {
rows: PropTypes.array,
cols: PropTypes.array,
};
(事实证明这些是我需要的而不是上面的 - 在整个组件中使用它们,但基本上从Comp
获取它们
<强> MenuBar.jsx 强>
MenuBar.propTypes = {
rows: PropTypes.array,
cols: PropTypes.array,
};
(与上面相同,在调用InsertRow时使用它们)
MenuBar也会像InsertRow
<li><InsertRow tableId={this.props.params.tableId} cols={this.props.cols} isDisabled={false} /></li>