We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在react中使用最多的应该就是setState吧,不然怎么改变视图!那么你真的了解setState吗?
在 React 日常的使用中,一个很重要的点就是,不要直接去修改 state。例如:this.state.count = 1是无法触发 React 去更新视图的。因为React的机制规定,一个state的更新,首先需要调用 setState 方法。
this.setState({ count: 1 })
这样便能触发重新渲染。稍有经验的开发者会知道,setState 方法其实是 “异步” 的。即立马执行之后,是无法直接获取到最新的 state 的,需要经过 React 对 state 的所有改变进行合并处理之后,才会去计算新的虚拟dom,再根据最新的虚拟dom去重新渲染真实dom。
class App extends Component { state = { count: 0 } componentDidMount(){ this.setState({count: this.state.count + 1}) console.log(this.state.count) // 0 } render(){ ... } }
那怎么才能获取到修改后的state呢?React为我们提供了一个回调去实现。
... this.setState({count: this.state.count + 1}, ()=>{ console.log(this.state.count) // 1 }) ...
回调里的 state 便是最新的了,原因是该回调的执行时机在于state合并处理之后。如果我们这样去做:
... this.setState({count: this.state.count + 1}) this.setState({count: this.state.count + 1}) ...
实际最终的 count 会等于 1,原因是执行时得到的this.state.count = 0。那怎么实现结果为 2 呢?
... this.setState(prevState => {count: prevState.count + 1}); this.setState(prevState => {count: prevState.count + 1}); ...
setState()实际上可以接受一个函数作为参数,函数的首个参数就是上一次的state。
以上介绍了setState的三种使用方式,下面我们来看看它们的执行时机是怎样的:
... this.setState({ count: this.state.count + 1 }); console.log("console: " + this.state.count); // 0 this.setState({ count: this.state.count + 1 }, () => { console.log("console from callback: " + this.state.count); // 2 }); this.setState(prevState => { console.log("console from func: " + prevState.count); // 1 return { count: prevState.count + 1 }; }, ()=>{ console.log('last console: '+ this.state.count) }); ...
执行结果:
console: 0 console from func: 1 console from callback: 2 last console: 2
React 其实会维护着一个 state 的更新队列,每次调用 setState 都会先把当前修改的 state 推进这个队列,在最后,React 会对这个队列进行合并处理,然后去执行回调。根据最终的合并结果再去走下面的流程(更新虚拟dom,触发渲染)。
因为setState()之后无法立马获取最新的 state,给人的感觉便是异步去设置状态。也确实是有异步的感觉(实 际原理后面讲诉)。那么为什么 React 要把状态的更新设计成这种方式呢?直接 this.state.count = 1不好吗?
有兴趣的可以点击看看:github
这边简单总结下:
我们先来看一段代码,执行前建议大家先预估下结果:
class App extends Component { state = { count: 0 }; componentDidMount() { // 生命周期中调用 this.setState({ count: this.state.count + 1 }); console.log("lifecycle: " + this.state.count); setTimeout(() => { // setTimeout中调用 this.setState({ count: this.state.count + 1 }); console.log("setTimeout: " + this.state.count); }, 0); document.getElementById("div2").addEventListener("click", this.increment2); } increment = () => { // 合成事件中调用 this.setState({ count: this.state.count + 1 }); console.log("react event: " + this.state.count); }; increment2 = () => { // 原生事件中调用 this.setState({ count: this.state.count + 1 }); console.log("dom event: " + this.state.count); }; render() { return ( <div className="App"> <h2>couont: {this.state.count}</h2> <div id="div1" onClick={this.increment}> click me and count+1 </div> <div id="div2">click me and count+1</div> </div> ); } }
探讨前,我们先简单了解下react的事件机制:react为了解决跨平台,兼容性问题,自己封装了一套事件机制,代理了原生的事件,像在jsx中常见的onClick、onChange这些都是合成事件。
那么以上4种方式调用setState(),后面紧接着去取最新的state,按之前讲的异步原理,应该是取不到的。然而,setTimeout中调用以及原生事件中调用的话,是可以立马获取到最新的state的。根本原因在于,setState并不是真正意义上的异步操作,它只是模拟了异步的行为。React中会去维护一个标识(isBatchingUpdates),判断是直接更新还是先暂存state进队列。setTimeout以及原生事件都会直接去更新state,因此可以立即得到最新state。而合成事件和React生命周期函数中,是受React控制的,其会将isBatchingUpdates设置为 true,从而走的是类似异步的那一套。
此处总结是直接引用了:你真的理解setState吗?
你真的理解setState吗?
浅入深出setState(上篇)
浅入深出setState(下篇)
The text was updated successfully, but these errors were encountered:
@LiPeiyang1211 Thank you, for sharing this to get more depth clarification while using setState and most helpful those references.
setState
Sorry, something went wrong.
No branches or pull requests
前言
在react中使用最多的应该就是setState吧,不然怎么改变视图!那么你真的了解setState吗?
如何使用setState
在 React 日常的使用中,一个很重要的点就是,不要直接去修改 state。例如:this.state.count = 1是无法触发 React 去更新视图的。因为React的机制规定,一个state的更新,首先需要调用 setState 方法。
这样便能触发重新渲染。稍有经验的开发者会知道,setState 方法其实是 “异步” 的。即立马执行之后,是无法直接获取到最新的 state 的,需要经过 React 对 state 的所有改变进行合并处理之后,才会去计算新的虚拟dom,再根据最新的虚拟dom去重新渲染真实dom。
那怎么才能获取到修改后的state呢?React为我们提供了一个回调去实现。
回调里的 state 便是最新的了,原因是该回调的执行时机在于state合并处理之后。如果我们这样去做:
实际最终的 count 会等于 1,原因是执行时得到的this.state.count = 0。那怎么实现结果为 2 呢?
setState()实际上可以接受一个函数作为参数,函数的首个参数就是上一次的state。
以上介绍了setState的三种使用方式,下面我们来看看它们的执行时机是怎样的:
执行结果:
React 其实会维护着一个 state 的更新队列,每次调用 setState 都会先把当前修改的 state 推进这个队列,在最后,React 会对这个队列进行合并处理,然后去执行回调。根据最终的合并结果再去走下面的流程(更新虚拟dom,触发渲染)。
setState为什么要设计成异步的
因为setState()之后无法立马获取最新的 state,给人的感觉便是异步去设置状态。也确实是有异步的感觉(实 际原理后面讲诉)。那么为什么 React 要把状态的更新设计成这种方式呢?直接 this.state.count = 1不好吗?
有兴趣的可以点击看看:github
这边简单总结下:
setState真的是异步吗
我们先来看一段代码,执行前建议大家先预估下结果:
探讨前,我们先简单了解下react的事件机制:react为了解决跨平台,兼容性问题,自己封装了一套事件机制,代理了原生的事件,像在jsx中常见的onClick、onChange这些都是合成事件。
那么以上4种方式调用setState(),后面紧接着去取最新的state,按之前讲的异步原理,应该是取不到的。然而,setTimeout中调用以及原生事件中调用的话,是可以立马获取到最新的state的。根本原因在于,setState并不是真正意义上的异步操作,它只是模拟了异步的行为。React中会去维护一个标识(isBatchingUpdates),判断是直接更新还是先暂存state进队列。setTimeout以及原生事件都会直接去更新state,因此可以立即得到最新state。而合成事件和React生命周期函数中,是受React控制的,其会将isBatchingUpdates设置为 true,从而走的是类似异步的那一套。
总结
此处总结是直接引用了:你真的理解setState吗?
参考
你真的理解setState吗?
浅入深出setState(上篇)
浅入深出setState(下篇)
The text was updated successfully, but these errors were encountered: