长春做网站,制作旅游网站网页的代码,wordpress 去购买按钮,wordpress建个人网站在类组件中使用setState#xff0c;在函数式组件中使用hooks的useState。 setstate目录 1. 类组件1.1 react 17版本1.2 react 18版本 2、函数式组件 1. 类组件
1.1 react 17版本
参考内容#xff1a;第十一篇#xff1a;setState 到底是同步的#xff0c;还是异步的在函数式组件中使用hooks的useState。 setstate目录 1. 类组件1.1 react 17版本1.2 react 18版本 2、函数式组件 1. 类组件
1.1 react 17版本
参考内容第十一篇setState 到底是同步的还是异步的 彻底搞懂setState到底是同步还是异步一
1、在react可调度范围内的setState是异步的并且多次setState会合并只执行最后一次进行批量更新。
react合成事件生命周期事件处理如onClick、onChange等。
2、在react可调度范围外的setState是同步的。
宏任务 setTimeout、setInterval微任务 .then原生 js 绑定事件 document.addEventListener()
3、setState 并非真正的异步而是通过设置全局变量 isBatchingUpdates 来判断 setState是先存进队列还是直接更新如果值为true则执行异步操作如果为false则直接更新。 isBatchingUpdates 会在 React 可以控制的地方则为true比如React生命周期和合成事件中而在外部 react 无法控制的地方比如原生事件具体就是在 addEventListener、setTimeout、setInterval 、.then等事件中就只能同步。
4、一般认为做异步设计是为了性能优化减少渲染次数。React团队的观点是
保持内部一致性。如果将 state 改为同步更新那尽管 state 的更新是同步的但是 props不是。启用并发更新完成异步渲染。
5、案例
import React from react;
export default class App extends React.Component{state {count: 0}increment () {console.log(increment setState前的count, this.state.count) //0this.setState({count: this.state.count 1}); //异步console.log(increment setState后的count, this.state.count) //0} //最终count变为1triple () {console.log(triple setState前的count, this.state.count) //1this.setState({count: this.state.count 1});this.setState({count: this.state.count 1});this.setState({count: this.state.count 1});//异步且合并console.log(triple setState后的count, this.state.count) //1} //最终count变为 2reduce () {setTimeout(() {console.log(reduce setState前的count, this.state.count) //2this.setState({count: this.state.count - 1});//同步 count变为 1console.log(reduce setState后的count, this.state.count) //1},0);}render(){return divbutton onClick{this.increment}点我增加/buttonbutton onClick{this.triple}点我增加三倍/buttonbutton onClick{this.reduce}点我减少/button/div}
}接着我把组件挂载到 DOM 上
import React from react;
import ReactDOM from react-dom;
import App from ./App;const rootElement document.getElementById(root);ReactDOM.render(React.StrictModeApp //React.StrictMode,rootElement
);此时浏览器里渲染出来的是如下图所示的三个按钮 此时有个问题若从左到右依次点击每个按钮控制台的输出会是什么样的 1.2 react 18版本
参考内容彻底搞懂setState到底是同步还是异步二 React18版本引入了自动批处理功能批处理是指当 React 在一个单独的重渲染事件中批量处理多个状态更新以此实现优化性能。如果没有自动批处理的话我们仅能够在 React 事件处理程序中批量更新。在 React 18 之前默认情况下 promise、setTimeout、原生应用的事件处理程序以及任何其他事件中的更新都不会被批量处理但现在这些更新内容都会被自动批处理。
1、在react18中setTimeout里的setState也是异步的批量处理了都是setTimeout 中的批处理明显落后外部的批处理。 上面代码在react18中的结果0 0 1 1 2 2.
2、案例
import React from react;
import ./App.css;class AppClass extends React.Component {state {count: 0,};handleClick () {this.setState({ count: 1 });console.log(count: , this.state.count); //0this.setState({ count: 2 });console.log(count: , this.state.count); //0//异步合并count的值变为2setTimeout(() {this.setState({ count: 3 });console.log(count: , this.state.count); //2this.setState({ count: 4 });console.log(count: , this.state.count); //2}, 0);//异步合并count的值变为4};render() {return (div classNameAppbutton onClick{this.handleClick}count {this.state.count}/button/div);}
}export default AppClass;react 18的控制台打印结果 react 17的打印结果 对比下结果
前两次的结果相同都是0证明这块是跟 v17 中一样的都是异步后两次结果不一样v17中是同步更新的所以每次setState 后都可以立即获取到更新后的值但v18 中打印的是两个2 说明是异步更新的只是这个异步更新跟setTimeout 外部的不在一个批中setTimeout 中的批处理明显落后外部的批处理。
页面会渲染几次 (执行setState会重新渲染页面)
react17中在setTimeout外会合并渲染一次在setTimeout中是同步的会渲染两次总共页面会渲染三次。react18中在setTimeout外会合并渲染一次在setTimeout中式异步的进行自动批处理会渲染一次总共页面会渲染两次。
2、函数式组件
参考内容彻底搞懂setState到底是同步还是异步三
函数式组件中使用hooks的useState。
1、react 17由于闭包输出的内容全部是count初始值。在setTimeout外部是异步批处理在setTimeout内部不是批处理与react 17中的类组件是否批处理一样。
2、react 18由于闭包输出的内容全部是count初始值。在setTimeout外部是异步批处理在setTimeout内部也是自动批处理与react 18中的类组件是否批处理一样。
3、案例 把上述题目改造成hooks的形式
import { useState } from react;
import ./App.css;function App() {const [count, setCount] useState(0);const handle () {setCount(1);console.log(count: , count); //0setCount(2);console.log(count: , count); //0setTimeout(() {setCount(3);console.log(count: , count); //0setCount(4);console.log(count: , count); //0}, 0);};return (div classNameAppbutton onClick{handle}count is {count}/button/div/);
}export default App;react 17的执行结果 react 18的执行结果 输出结果都是0看似都是在批处理为了能更清楚的看到 React 的渲染行为修改下上边的代码在每次渲染都都打印下当前的 count值添加如下代码
useEffect(() {console.log(render: 此时的count: , count);});再次查看输出结果 分析下
在 React 17 下render 打印了 3 次说明组件重新渲染了 3 次回顾下当时讲解 React 17 的 setState时setTimeout外是批处理重新渲染一次setTimeout中是同步渲染重新渲染两次能对上。再来看下 React 18 下render 打印了 2 次说明组件重新渲染了 2 次在对比下前面讲解的 React18 的自动批处理功能setTimeout外部批处理一次内部批处理一次重新渲染两次也能对上.那为什么这期间打印的 count 都是 0 呢 这是由于js的特性闭包导致的闭包就是内部函数可以访问外部函数的变量。 组件App是一个函数handle 是 App内的函数这也就形成了一个闭包所以 handle 函数才能访问到 count 变量的值。 无论延时多长时间最终打印的count值一直是旧值也就是 0。 要是想要立即用更新后的state可以使用setState的第二个函数。