我将 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 来替换它,但这似乎非常不 react 。 - 我也可以为应用的 DisplayTable 部分制作另一个菜单,但我正在努力避免困惑。
(如果与答案相关,我不会使用React Router 4.0,而是使用最新版本的 meteor 3.0.5,尽管我猜这与此上下文无关)
编辑:我想我将在路径上方添加容器,这样我就已经有了数据。有点道理,但我会将其留在这里以防有人有更好的建议。
最佳答案
虽然可能有更好的方法来做到这一点,但我将在下面解释我最终做了什么:
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时使用它们)
菜单栏还调用InsertRow
像这样:<li><InsertRow tableId={this.props.params.tableId} cols={this.props.cols} isDisabled={false} /></li>
关于javascript - React-Router 在主组件和侧边栏组件之间传递 props,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43649430/