zoukankan      html  css  js  c++  java
  • react与mox-react的shouldComponentUpdate 理解

    react性能优化中,提到的就是通过 React.PureComponent 替换 React.Component 组件进行编程。

    两个组件之间的不同主要就是PureComponent做了shouldComponentUpdate的优化。对props和state进行了第一层的值===比较, 并且对 context 的变化不进行判断。

    通过查看React可以看到

     1 /**
     2  * Copyright (c) 2013-present, Facebook, Inc.
     3  * All rights reserved.
     4  *
     5  * This source code is licensed under the BSD-style license found in the
     6  * LICENSE file in the root directory of this source tree. An additional grant
     7  * of patent rights can be found in the PATENTS file in the same directory.
     8  *
     9  * @typechecks
    10  * 
    11  */
    12 
    13 /*eslint-disable no-self-compare */
    14 
    15 'use strict';
    16 
    17 var hasOwnProperty = Object.prototype.hasOwnProperty;
    18 
    19 /**
    20  * inlined Object.is polyfill to avoid requiring consumers ship their own
    21  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
    22  */
    23 function is(x, y) {
    24   // SameValue algorithm
    25   if (x === y) {
    26     // Steps 1-5, 7-10
    27     // Steps 6.b-6.e: +0 != -0
    28     // Added the nonzero y check to make Flow happy, but it is redundant
    29     return x !== 0 || y !== 0 || 1 / x === 1 / y;
    30   } else {
    31     // Step 6.a: NaN == NaN
    32     return x !== x && y !== y;
    33   }
    34 }
    35 
    36 /**
    37  * Performs equality by iterating through keys on an object and returning false
    38  * when any key has values which are not strictly equal between the arguments.
    39  * Returns true when the values of all keys are strictly equal.
    40  */
    41 function shallowEqual(objA, objB) {
    42   if (is(objA, objB)) {
    43     return true;
    44   }
    45 
    46   if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
    47     return false;
    48   }
    49 
    50   var keysA = Object.keys(objA);
    51   var keysB = Object.keys(objB);
    52 
    53   if (keysA.length !== keysB.length) {
    54     return false;
    55   }
    56 
    57   // Test for A's keys different from B.
    58   for (var i = 0; i < keysA.length; i++) {
    59     if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
    60       return false;
    61     }
    62   }
    63 
    64   return true;
    65 }
    66 
    67 module.exports = shallowEqual;
    shallowEqual

    项目准备升级 React16,控制台出现了错误 shouldComponentUpdate should not be used when extending React.PureComponent.

    一开始看很莫名其妙,明明组件没有自己写shouldComponentUpdate,怎么就报错了。

    后来谷歌了下,原来是项目使用了mobx进行的状态管理。使用mox-react,对所有组件都通过 @observer 装饰器,以前也看过mobx-react源码,里面的确mixin了shouldComponentUpdate方法,优化了组件的性能

    看下面的源代码

     1 function mixinLifecycleEvents(target) {
     2     patch(target, "componentWillMount", true)
     3         ;["componentDidMount", "componentWillUnmount", "componentDidUpdate"].forEach(function (
     4             funcName
     5         ) {
     6             patch(target, funcName)
     7         })
     8     if (!target.shouldComponentUpdate) {
     9         target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate
    10     }
    11 }
    12 {
    13     shouldComponentUpdate: function(nextProps, nextState) {
    14         if (isUsingStaticRendering) {
    15             console.warn(
    16                 "[mobx-react] It seems that a re-rendering of a React component is triggered while in static (server-side) mode. Please make sure components are rendered only once server-side."
    17             )
    18         }
    19         // update on any state changes (as is the default)
    20         if (this.state !== nextState) {
    21             return true
    22         }
    23         // update if props are shallowly not equal, inspired by PureRenderMixin
    24         // we could return just 'false' here, and avoid the `skipRender` checks etc
    25         // however, it is nicer if lifecycle events are triggered like usually,
    26         // so we return true here if props are shallowly modified.
    27         return isObjectShallowModified(this.props, nextProps)
    28     }
    29 }
    30 function isObjectShallowModified(prev, next) {
    31     if (null == prev || null == next || typeof prev !== "object" || typeof next !== "object") {
    32         return prev !== next
    33     }
    34     const keys = Object.keys(prev)
    35     if (keys.length !== Object.keys(next).length) {
    36         return true
    37     }
    38     let key
    39     for (let i = keys.length - 1; i >= 0, (key = keys[i]); i--) {
    40         if (next[key] !== prev[key]) {
    41             return true
    42         }
    43     }
    44     return false
    45 }

    经过测试,使用setState后,shouldComponentUpdate 的确 this.state!==nextState,但是对于this.props, nextProps的判断,还是存在一些差别的。

    可以试下下面的比较 

    console.log(isObjectShallowModified(NaN, NaN), !shallowEqual(NaN, NaN));

    var a = {a: 1}, b = {b: 1, __proto__: {a: 1}};
    console.log(isObjectShallowModified(a, b), !shallowEqual(a, b));

    对于一些比较简单的对象比较结果还是相同的,所以对于@observer的组件就改为了React.Component进行处理。

  • 相关阅读:
    eclipse导入项目后出现红色叉号
    java.lang.ArithmeticException: Non-terminating decimal expansion
    IDEA 2020 注册码
    最新调查:游戏女性玩家群体达3亿!这意味着什么,嘻嘻......
    Linux安装配置Nginx服务器
    mysql/mariadb 远程登陆
    redis 集群 新增 master 节点 与 slave 挂靠命令
    RedisCluster 集群 之 Ruby 安装
    Linux CentOS 7 关闭防火墙
    springcloud 与 springboot 对应关系
  • 原文地址:https://www.cnblogs.com/legu/p/7834112.html
Copyright © 2011-2022 走看看