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

无法回避的setState问题

时间:2023-03-17 12:45:45 科技观察

本文转载自微信公众号《Gogo的前端世界》,作者西岭。转载本文请联系Gogo前端世界公众号。AsynchronoussetState"setState是异步的还是同步的?"这是面试中经常被问到的经典面试题。在开始讲解异步特性之前,我们需要先明确一点,从API层面来说,是正常调用执行的函数,自然是同步API。所以这里所说的同步和异步是指API调用后状态发生变化或者更新DOM的时机是同步的还是异步的。先看一段代码:importReact,{Component}from'react'exportclassStatesextendsComponent{state={name:"lisi",age:18}fun=()=>{this.setState({name:'xiling'})console.log(this.state.name)}render(){return(

状态组件

{this.state.name}

{this.fun()}}>点我
)}}exportdefaultStates代码实现的功能很简单,就是修改state之后的name属性的值点击按钮。在事件处理函数中,调用setState方法后,将状态值打印到控制台。运行代码,你会发现Dom中的值变了,但是控制台还是之前的结果值。如果熟悉异步操作规则,就不会感到惊讶。很明显,this.setState()是异步执行的。调用后,下面的代码会立即执行。所以控制台打印的结果一定是修改前的结果。因此,我们可以确定this.setState()确实是异步调用执行的代码。请注意,此时,您可以将this.setState()视为普通的异步执行代码(同样,JSX是JS)。那么,如果我想调整代码来获取异步执行的结果,该怎么办呢?既然可以看成是普通的异步代码,想了想就知道了,其实this.setState()方法还提供了第二个参数,我们可以传入一个回调函数,这个函数就是之后执行的回调函数异步端,具体代码修改如下:fun=async()=>{awaitthis.setState({name:'xiling'},()=>{console.log(this.state.name)})}回调函数处理异步结果是传统的异步编码方式,但是我们也知道异步回调函数最大的问题就是“回调地狱”,那么既然是异步的,我们是不是可以封装一个Promise呢?当然!然而,封装一个Promise有点复杂。最简单的方法是使用ES2017异步调用函数async/await。我们可以直接修改事件处理函数。具体语法规则如下:fun=async()=>{awaitthis.setState({name:'xiling'})console.log(this.state.name)}setState的执行逻辑在使用this的时候。setState()改变状态,逻辑处理应该怎么做?其实this.setState()的第一个参数可以接收一个函数进行处理。需要注意的是函数的运行必须返回一个状态对象,具体代码如下:fun=()=>{this.setState((state)=>{//函数逻辑代码...letreturnDatareturnData=state.age+1//最后返回一个状态对象return{age:returnData}})}也就是说this.setState()既可以接收对象参数,也可以接收一个处理函数。那么,两者有什么区别呢?在时间处理函数中,我们两次使用this.setState()来修改状态。两个函数执行操作:fun=()=>{this.setState((state)=>{return{age:state.age+2}})this.setState((state)=>{return{age:state。age+3}})}运行代码,可以发现this.setState()中的函数被执行了两次,修改了state的值。让我们使用相同的代码逻辑来修改对象数据:fun=()=>{this.setState({age:this.state.age+2})this.setState({age:this.state.age+3})}结果显示只执行了最后一个this.setState()。没错,如果this.setState()是一个函数,那么这个函数会从上到下依次执行;如果它是一个对象,React会将多次调用this.setState()合并到一次执行中。如果相同的值,以前的修改将替换为最后修改的数据。在项目编码中必须牢记这一点,以避免意外的逻辑错误。你可能会问,这是什么原理?我曾经针对这个问题做过专题技术分享直播。现场录音和回放在这里。有兴趣的可以看看:https://www.bilibili.com/video/BV19P4y1W7hX。(B站账号:西陵老师)不过,新手还是建议先收藏一下,因为你现在可能真的看不懂。当然,你也可能发现了问题。关于组件的状态我们已经说了这么多。各种实验编码在类组件中完成。函数组件和类组件一样吗?嗯~o( ̄▽ ̄)o...,因为state是类组件中的特性,而函数组件中的state需要Hook特性的知识作为铺垫,所以暂时先留个坑和等待它稍后被填充。.至此,我们已经掌握了组件的概念,组件的传值,组件状态的相关内容。