我正在使用React + Redux,并想知道如何正确更新状态。
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/questions" component={App}>
<Route path="subject">
<Route path="english" component={displayQuestions} />
<Route path="math" component={displayQuestions} />
<Route path="science" component={displayQuestions} />
<Route path="history" component={displayQuestions} />
</Route>
</Route>
...
</Router>
</Provider>
, document.querySelector('.app'));
可以使用标签点击这些路线(此处显示一个示例):
<div>
<Link to={'/questions/english'}>English</Link>
</div>
...
在我的displayQuestions渲染方法中,我做了一个检查
if (!questions) {
Loading content
}
return (
{this.renderQuestions()}
)
因此,当用户导航到该页面时,在我的componentDidMount()中,我使用了一个操作方法this.props.fetchQuestions,然后它向我的后端发出异步请求,通过reducers然后进入渲染上面的方法。在renderQuestions函数中,在renderQuestions中,我只是从this.props.questions中获取问题。
但是,我配置路由的方式,componentDidMount只出现一次。例如,如果我在英文选项卡上选择,我会得到componentDidMount,但是如果我然后点击数学或科学,则网址会更改,但不会再次调用componentDidMount。
如果我点击了一个按钮,它使用了另一个组件,比如userProfile,那么所有内容都会按预期重新呈现。但我认为,因为我在每个问题/主题路径中使用相同的组件,所以不会再次调用componentDidMount。
那么如何更新网址更改的状态?什么是React + Redux方式?请不要反模式。
编辑:
目前,我已经回答了这个问题:
componentDidUpdate(nextProps) {
if (this.props.route.path !== nextProps.route.path) {
let subject = this.props.location.pathname.split('/')[3];
this.props.fetchQuestions(subject);
}
return false;
}
这会停止原本会发生的无限循环。但必须有更好的方法。
答案 0 :(得分:1)
我不知道组件的确切布局,但听起来像“Tabs”组件都是一次安装一个组件。如果是这种情况,那么可能有一些州控制哪个标签显示正确?然后,您可以在componentWillReceiveProps
中检查道具何时更改为问题标签。如果它已经执行了异步请求。
例如
componentWillReceiveProps(nextProps) {
if (nextProps.tab === 'questionTab' && this.props.tab !== 'questionTab' ) {
this.props.fetchQuestions();
}
}
答案 1 :(得分:1)
链接to property可以接收LocationDescriptor对象,而不仅仅是路径名。使用位置描述符,您可以传递一个可以在组件componentWillReceiveProps方法中检查的状态。但是,组件安装时不会调用componentWillReceiveProps,因此您还必须在组件安装时进行此调用 - componentWillMount。最好使用一个方法来获取,并从它们中调用它:
<div>
<Link to={
pathname: '/questions/subject',
state: { subject: 'english'}
}>English</Link>
<Link to={
pathname: '/questions/subject',
state: { subject: 'science'}
}>English</Link>
</div>
/** now you can declare only one route, and the state invokes the change **/
<Route path="/questions" component={App}>
<Route path="subject" component={displayQuestions} />
</Route>
class displayQuestions extends React.Component {
_updateQuestions(props, nextProps) {
const currentSubject = props.location.state.subject; // the current subject
const nextSubject = nextProps ? nextProps.location.state.subject : null; // the nextSubject (componentWillReceiveProps) or null (componentWillMount)
if(currentSubject === nextProps) { // if the subjects are equal do nothing
return;
}
props.fetchQuestions(nextSubject || currentSubject); // fetch the questions of nextSubject (componentWillReceiveProps) or currentSubject (componentWillMount)
}
componentWillMount() {
_updateQuestions(this.props);
}
componentWillReceiveProps(nextProps) {
_updateQuestions(this.props, nextProps);
}
}