在 React 中,组件状态的改变是通过 setState
方法实现的。然而有时候我们会发现,调用 setState
方法后,组件的状态并没有发生改变,这时候我们就需要了解造成这种情况的原因。
原因一:异步更新
React 中的 setState 方法是异步更新的,也就是说,我们不能保证 setState
方法何时执行完毕,因为它可能等待其他代码执行完毕后再去执行。这可能导致在我们执行 setState
方法后,立即去访问 state 中的变量会得到旧的值,而不是更新之后的值。例如:
handleClick() { this.setState({ count: this.state.count + 1 }); console.log(this.state.count); // 点击按钮后输出的是更新前的 count 值 }
解决这个问题一般有两种方法:
- 在
setState
方法的回调函数中去访问 state 的更新值,因为在回调函数中可以保证 state 已经更新。例如:
handleClick() { this.setState({ count: this.state.count + 1 }, () => { console.log(this.state.count); // 输出更新后的 count 值 }); }
- 使用
setTimeout
去等待一段时间后再去访问 state 的更新值。例如:
handleClick() { this.setState({ count: this.state.count + 1 }); setTimeout(() => { console.log(this.state.count); // 等待 0ms 后输出更新后的 count 值 }, 0) }
当然,如果你使用了 React.StrictMode
,你会发现在控制台中会出现警告,提示我们不能再 setTimeout
中去访问 state,这是 React 为了安全起见设定的。不过,如果你觉得不使用 React.StrictMode
也没关系,可以在 setTimout 中添加 try-catch 语句把警告消除。
setTimeout(() => { try { console.log(this.state); } catch (e) {} }, 0)
原因二:同步更新
除了异步更新外,可能还存在同步更新的情况。在处理一些复杂计算的场景下,你只需要在函数中调用几次 setState,而虽然调用了 setState,但在函数结束前连同组件一起卸载,这个时候虽然我们调用了 setState ,但它已经不会起到任何效果。这种情况下可以使用 isMounted
的方式去判断组件是否还在页面上渲染,如果组件已经 unmount,就没有必要再去更新组件状态了。
if (this.ref.current && this.ref.current.isMounted()) { this.setState({ result: calculate(), }); }
原因三:使用不当
在 setState 的调用过程中还有一些使用不当的情况会导致无更新,例如,使用不正确的 state 引用,或者把 shouldComponentUpdate 强制设为 false,等等。
使用不正确的 state 引用
在 React 中有些情况下同时存在两个不同的 state,这时候可能会发生使用错误的情况。例如:
this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count - 1 });
这段代码的本意是让 count 加 1 再减 1,但实际上它会让 count 减 1,因为第二个 setState 会使用第一个 setState 引用时的旧值减去 1。
我们可以改成以下代码:
this.setState(prevState => ({ count: prevState.count +1 })); this.setState(prevState => ({ count: prevState.count -1 }));
这样就避免了使用不正确的 state 引用了。
shouldComponentUpdate 被强制设为 false
shouldComponentUpdate 是 React 中用来控制组件是否重新渲染的方法,它默认返回 true,表示组件每次 setState 时都会重新渲染。但当我们将 shouldComponentUpdate 的返回值设置为 false 时,组件就不会重新渲染。这样,我们的 setState 就会无效了。
总结
- 在 React 中,setState 方法是异步更新的,不能保证在调用之后立即更新。
- 在 setState 方法的回调函数中去访问 state 的更新值,或者使用 setTimeout 去等待一段时间后再去访问 state 的更新值。
- 当需要在一些复杂计算的场景下进行 setState 调用时,可以使用 isMounted 判断组件是否还在页面上渲染。
- 使用不正确的 state 引用时可能会导致 setState 无效。
- 将 shouldComponentUpdate 的返回值设置为 false 时,组件就不会重新渲染,这样 setState 就会无效了。
希望这篇文章可以帮助你更好的理解 React 中 setState 方法无效的原因,并提供一些建议来解决这样的问题。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/645c3ad3968c7c53b0e81543