当前位置: 首页 > 科技观察

面试官:说说React中的SetState执行机制

时间:2023-03-23 11:52:33 科技观察

本文转载自微信公众号《JS每日一问》,作者灰灰。转载本文请联系JS每日一问公众号.1、组件的显示形式是什么?可以通过数据状态和外部参数来确定,数据状态就是状态。当需要修改里面的值的状态时,需要调用setState来改变,从而达到更新组件内部数据的功能。下面的例子:importReact,{Component}from'react'exportdefaultclassAppextendsComponent{constructor(props){super(props);this.state={message:"HelloWorld"}}render(){return(

{this.state.message}

this.changeText()}>面试官系列
)}changeText(){this.setState({message:"JS日报question"})}}通过点击按钮触发onclick事件,执行this.setState方法更新state状态,然后重新执行render函数,会导致页面的view更新。如果直接修改state的状态,如下:changeText(){this.state.message="JSDailyQuestion";}我们会发现页面不会响应,但是state的状态发生了变化。这是因为React不像vue2中调用Object.defineProperty数据响应或者Vue3调用Proxy必须使用setState方法通知react组件状态发生了变化。状态方法的定义继承自React.Component。定义的源码如下:Component.prototype.setState=function(partialState,callback){invariant(typeofpartialState==='object'||typeofpartialState==='function'||partialState==null,'setState(...):takesanoobjectofstatevariablestoupdateora'+'返回状态变量对象的函数。',);this.updater.enqueueSetState(this,partialState,callback,'setState');};从上面我们可以看出,setState的第一个参数可以是一个对象,也可以是一个函数,第二个参数是一个回调函数,用于实时获取更新后的数据。2、更新类型使用setState更新数据时,setState的更新类型分为:异步更新同步更新异步更新先举个例子:changeText(){this.setState({message:"Hello"})console.log(this.state.message);//HelloWorld}从上面可以看出,最终的打印结果是Helloworld,不能执行setState后立即获取最新状态结果,如果想立即获取更新后的值,changeText()会在第二个参数的回调中更新后执行{this.setState({message:"Hello"},()=>{console.log(this.state.message);//Hello});}同步更新也先给出setTimeout中更新的例子:changeText(){setTimeout(()=>{this.setState({message:"Hello});console.log(this.state.message);//Hello},0);}在上面的示例中,您可以看到更新是同步的原生DOM事件的示例:componentDidMount(){constbtnEl=document.getElementById("btn");btnEl.addEventListener('click',()=>{this.setState({message:"Hello"});console.log(this.state.message);//Hello})}总结在组件生命周期或者React合成事件中,setState在set中是异步的在Timeout或原生DOM事件中,setState是同步的。3.批量更新也先举个例子:handleClick=()=>{this.setState({count:this.state.count+1,})console.log(this.state.count)//1this.setState({count:this.state.count+1,})console.log(this.state.count)//1this.setState({count:this.state.count+1,})console.log(this.state.count)//1}点击按钮触发事件,打印的都是1,页面显示count的值为2。多次为同一个值setState,setState的批量更新策略会覆盖掉并取最后的执行结果。上面的例子其实等同于:Object.assign(previousState,{index:state.count+1},{index:state.count+1},...)由于后面的数据会覆盖前面的变化,最后只添加一次。如果下一个状态依赖于上一个状态,建议给setState传入一个函数作为参数,如下:onClick=()=>{this.setState((prevState,props)=>{return{count:prevState.count+1};});this.setState((prevState,props)=>{return{count:prevState.count+1};});}但是,在setTimeout或原生DOM事件中,因为它是一个同步操作,不会被覆盖。com/a/1190000039077904