我遇到了react-router版本3的问题,我将路由状态作为道具传递,以及更新父状态值的点击处理程序。
虽然在主页组件中点击后,父 sidebarOpen 状态值会发生变化,但 sidebarState 值仍保留在初始值 false 。
当路由器类中的状态发生变化时,有没有办法确保将更新的状态值传递给接收组件?
首先点击:
sidebarOpen:假
sidebarState:false
第二次点击:
sidebarOpen:真
sidebarState:false
第三次点击:
sidebarOpen:假
sidebarState:false
var Home = React.createClass({
handleViewSidebar: function(){
this.props.route.clickHandler();
console.log('sidebarState:' + this.props.route.sidebarState);
},
render: function() {
return (
<div>
<Header onClick={ this.handleViewSidebar } />
<SideBar isOpen={ this.props.route.sidebarState } onClick={ this.handleViewSidebar } />
<Content isOpen={ this.props.route.sidebarState } />
</div>
);
}
});
var App = React.createClass({
getInitialState: function(){
return {sidebarOpen: false};
},
handleViewSidebar: function(){
this.setState({sidebarOpen: !this.state.sidebarOpen});
console.log('sidebarOpen:' + this.state.sidebarOpen);
},
render: function() {
return (
<Router history={ hashHistory }>
<Route path="/"
sidebarState={ this.state.sidebarOpen }
clickHandler={ this.handleViewSidebar }
component={ Home }>Home</Route>
<Route path="/about"
sidebarState={ this.state.sidebarOpen }
clickHandler={ this.handleViewSidebar }
component={ About }>About</Route>
<Route path="/contact"
sidebarState={ this.state.sidebarOpen }
clickHandler={ this.handleViewSidebar }
component={ Contact }>Contact</Route>
</Router>
);
}
});
ReactDOM.render(<App />, document.getElementById('app'));
答案 0 :(得分:4)
我的建议是重构您的组件,以便您拥有:
仅处理路由的根组件
一个App组件,它将包含其他路由的组件以及句柄侧栏逻辑和状态
您的其他组件(Home,About,Contact)将是App的子路由,因此可以通过props继承状态和处理程序。
然后,您可以React.Children.map超过this.props.chidren
属性(当您在其他路由中嵌套路由时,由React-Router提供给App),然后使用React.cloneElement创建子项并分配它们状态和处理程序通过道具。
所以你的代码看起来像这样:
var Routes = React.createClass({
render: function() {
return (
<Router history={ hashHistory }>
<Route path="/" component={App}>
<IndexRoute component={ Home }>Home</Route>
<Route path="/about" component={ About }>About</Route>
<Route path="/contact" component={ Contact }>Contact</Route>
</Route>
</Router>
);
}
});
var App = React.createClass({
getInitialState: function(){
return {sidebarOpen: false};
},
handleViewSidebar: function(){
this.setState({sidebarOpen: !this.state.sidebarOpen});
},
render: function() {
const childWithProps =
React.Children.map(
this.props.children,
child => {
return (
React.cloneElement(child, {
sidebarOpen : this.state.sidebarOpen,
handleViewSidebar: this.handleViewSidebar
}
)
}
)
return (
<div>
{childWithProps}
</div>
);
}
});
ReactDOM.render(<App />, document.getElementById('app'));