答案: 我是个傻瓜。这是迟到的,但不想留下未回复的帖子,特别是因为我最初的回答是错误。我需要引用我得到的 new 道具,而不是 this.props 。像往常一样,答案是documentation。我在下面更新了自己的答案以反映这一点。
编辑1: 我的第一个小提琴没有完全显示我的问题,所以我updated it更好地证明了这一点。出于某种原因,当我调用 setState()时,我认为第一次通过它是未定义的,即使它给定了一个值,但在后续传递中它按预期工作。看起来我的初始 setState()调用没有触发重新渲染,但其他所有调用都是。
与通常的" setState不更新视图有点不同"问题为 setState()正在更新我的视图并使用正确的值。就在我不期待的时候。基本上我触发一个setState()事件应该用新的道具重新渲染我的子组件,我相信它应该触发子组件componentWillReceiveProps lifecyle事件,然后在子组件中调用 setState()并更新它视图。问题是,当它确实更新视图时,它似乎在预期时落后一个循环。在我的MVP中,我在2秒时调用 setState(),但它在4秒时更新了视图。我虽然无法确定哪个部分是错误的逻辑。
这是我的jsFiddle MVP。感谢您的任何建议。
代码:
class TaskBody extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentWillReceiveProps() {
this.setState({
activeTask: this.props.activeTask
});
}
render() {
return <div>
< h4 > {
this.state.activeTask ? this.state.activeTask : 'Task Title'
} < /h4>
< /div > ;
}
}
class Body extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTask: '',
counter: 1
};
this.updateActive = this.updateActive.bind(this);
}
updateActive(task) {
this.setState({
activeTask: task
});
}
componentDidMount(){
var self = this;
setInterval(function(){
if(self.state.counter === 4){
clearInterval(self.clickInterval);
return clearInterval(self.countInterval);
}
self.setState({ counter: self.state.counter + 1 });
}, 1000);
// imagine this was the click event, it should rerender the view
// instantaneously at 2 seconds because I called setState() right?
// which is supposed to trigger a re-render and then TaskBody should
// receive new props triggering it to setState() on its activeTask,
// which should update the view?
self.clickInterval = setInterval(function(){
self.setState({ activeTask: 'took double the time it should' });
}, 2000);
}
render() {
return <div>
< TaskBody activeTask = {
this.state.activeTask
}/>
<div>{this.state.counter}</div>
</div>;
}
}
ReactDOM.render(<Body />, document.querySelector('#body'));
答案 0 :(得分:0)
self.setState({ activeTask: 'took double the time it should' });
实际上从未被调用过。
原因如下:
您的逻辑位于componentDidMount
生命周期方法中。如果您阅读the documentation of componentDidMount
,您会看到它明确指出:
立即仅在客户端(不在服务器上)调用一次 初始渲染发生后。
因此,当您在应用中调用componentDidMount
时,您首先会检查计数器并在那里调用setState
。仅这一点就会触发一个新的渲染。这意味着componentDidMount
中的第二个代码块将无效,因为在设置方法时,它永远不会被调用。
答案 1 :(得分:0)
在我的旧答案中,我使用setTimeout()作为黑客来获得我想要的结果。基本上,如果我在超时中包装我的setState,它将使用新的道具设置状态,但如果我没有,它仍然会引用旧的道具。幸运的是,这已经在react中处理,因为componentWillReceiveProps默认已经接收到newProps参数。
此:
componentWillReceiveProps(){
var self = this;
setTimeout(function(){
self.setState({activeTask: self.props.activeTask});
},0);
}
变为
componentWillReceiveProps(newProps){
var self = this;
self.setState({activeTask: newProps.activeTask});
}