最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【七日打卡】React中state状态更新那些事

    正文概述 掘金(wangly19)   2021-01-18   592

    简介

    最近听到很多小伙伴面试题上都会碰到一道比较经典的React批量更新(状态合并)的题目,每个人都有各的答法,但其实很少有人能够非常好的给出这一题目的答案,如果你刚好在准备明年跑路,那么这一题看了可能会给你无形中给与一个帮助。

    那么,请看题目

    • class 组件中,以下代码同时执行究竟会渲染几次视图,请结合场景作答?
    // state默认所有值初始化都为0
    
    this.setState({ a: 1 })
    this.setState({ b: 1})
    this.setState({ c: 1 })
    

    上述题中,主要问的知识点就是React的渲染更新问题,分别是有状态组件和无状态组件在更新state行为的一个作用变化结果的思考。如果你平时善于实践,那么这种题目实际上算是送分题,通过不难,但是回答的满意就很让人头疼了,这个题目能够向下深挖出对React机制的一些理解。

    什么是批量更新?

    React Class Component中,setState会触发DOM的一个render,其实也变相的是激发Virtual-Dom的一个更新行为,那么批量更新的操作模式就诞生了。

    我们在消费一件商品的时候,扫码支付并不会故意存在分多个批次给商家转账的情况,而是一次性转入到账。所以,在一笔消费的方法中,所有setState其实本身只需要进行付账一次,就好比去超市购物,购物车里面有非常的东西,但是我们最终都是统一结账掉的,并不是买一件,付一件。

    因此,setState,看起来是下面这个样子的,在同一批次的setState的值,都会被添加到合并队列中去,进行一个state合并的过程。

    setState<K extends keyof S>(
      state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
      callback?: () => void
    ): void;
    
    forceUpdate(callback?: () => void): void;
    

    举个例子:如下,就是一个未合并之前的一个函数行为,分别分三次设置了不同的state的值。如果不加以处理,那么将会渲染三次render函数的触发。

    合并前 =>

    this.setState({a: 1})
    this.setState({b: 1})
    this.setState({c: 1})
    

    可以看到三次行为都被拉入一批队列中,进行了值合并。

    合并后 =>

    this.setState({
    	a: 1,
        b: 1,
        c: 1,
    })
    

    异步触发更新时

    虽然React为我们做了更新的合并,但是这往往都是取决于React能够鉴定你触发更新行为的时候。但是,当我们的setState在异步中的时候,React并不知道我们还有更新需要执行,因此,他以为你这个函数不需要合并更新,那么它就不会给你进行一个state 合并的操作了。可以看【七日打卡】React中state状态更新那些事下面这张运行图:

    【七日打卡】React中state状态更新那些事

    在执行Promise结果中处理的setState并没有合并,依旧被执行了三次,意味着render视图被执行了三次更新,这个无疑是非常浪费,对性能来说产生了无意义的开销。

    那么到了这里,大家获取就明白了很多了,如果我们使用了React本身无法监听调度的API的话,setState的事件合并就需要开发者来做调度了。

    调度更新

    React中,暴露出两个可以自主触发视图更新的API能够给开发者手动更新。

    forceUpdate

    forceUpdate就非常好理解了,调用这个函数的时候会直接强制刷新。传入的函数则是刷新后的一个回调事件。从下面类型推导来看的话,它的作用并不理想(不推荐使用),对正常开发情况下来说,如果需要涉及强制更新的话,往往是代码存在一些问题,大多数情况下都不需要使用到。

    forceUpdate(callback?: () => void): void;
    

    unstable_batchedUpdates

    unstable_batchedUpdates则是手动合并处理事件了,之前的更新调度是React帮我们做的,而现在的话相当于我们自己去声明自己的调度,来主动合并事件。

    但是,细心的小伙伴可能发现了, unstable_batchedUpdates带了unstable来表明是不稳定的,虽然说使用上来讲是没有问题,但还是不推荐进行使用。

    handelClick = () => {
        mockData().then(() => {
          margeUpdate(() => {
            this.setState({a: 1})
            this.setState({b: 1})
            this.setState({c: 1})
          })
        })
      }
    

    【七日打卡】React中state状态更新那些事

    开发时合并

    更加理想的情况下是主动在开发时,能够合并的State尽量合并成为一个对象,而不是拆成零散的属性,这样对React的一些分担压力还是蛮大的。

    // 未合并
    
    state = {
      a: 1,
      b: 2,
      c: 3
    }
    
    // 合并
    
    state = {
    	obj: {
        a: 1,
        b: 2,
        c: 3
      }
    }
    
    

    看看Hooks

    其实函数组件也有相似的问题,而且更加的直观,因为函数组件本身没有状态,所有的状态行为都来自于副作用,当副作用频繁触发的时候,useEffect相关满足依赖的行为可能会被频繁的触发。

    【七日打卡】React中state状态更新那些事

    总结

    不论是在函数组件还是Class组件,在开发的时候都需要合理根据业务定制好state的数据结构,这样的话在后续做数据更新时,才可能尽量少的情况下做视图更新,节省性能。

    承上启下,那么开头的问题,你知道怎么回事了吗。


    起源地下载网 » 【七日打卡】React中state状态更新那些事

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元