加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

React 性能优化技巧总结

发布时间:2019-02-26 14:03:13 所属栏目:建站 来源:落在起风的地方
导读:本文将从 render 函数的角度总结 React App 的优化技巧。需要提醒的是,文中将涉及 React 16.8.2 版本的内容(也即 Hooks),因此请至少了解 useState 以保证食用效果。 正文开始。 当我们讨论 React App 的性能问题时,组件的渲染速度是一个重要问题。在进

如果这条建议可以让我们避免不必要的重新渲染,那我们为什么不把每个 class 组件变成 PureComponent、把每个函数式组件用 React.memo 包起来?为什么有了更好的方法还要保留 React.Component 呢?为什么函数式组件不默认记忆化呢?

毫无疑问,这些方法并不总是万灵药。

嵌套对象的问题

我们先来考虑下 PureComponent 和 React.memo 的组件到底做了什么?

每次更新的时候(包括状态更新或上层组件重新渲染),它们就会在新 props、state 和旧 props、state 之间对 key 和 value 进行浅比较。浅比较是个严格相等的检查,如果检测到差异,render 就会执行:

  1. // 基本类型的比较  
  2. shallowCompare({ name: 'bar'}, { name: 'bar'}); // output: true  
  3. shallowCompare({ name: 'bar'}, { name: 'bar1'}); // output: false  

尽管基本类型(如字符串、数字、布尔)的比较可以工作的很好,但对象这类复杂的情况可能就会带来意想不到的行为:

  1. shallowCompare({ name: {first: 'John', last: 'Schilling'}},  
  2.                { name: {first: 'John', last: 'Schilling'}}); // output: false  

上述两个 name 对应的对象的引用是不同的。

我们重新看下之前的例子,然后修改我们传入 Bar 的 props:

  1. import React, { useState } from "react";  
  2. import ReactDOM from "react-dom";  
  3.   
  4. const Bar = React.memo(function Bar({ name: { first, last } }) {  
  5.   console.log("Bar render");  
  6.   
  7.   return (  
  8.     <h1>  
  9.       {first} {last}  
  10.     </h1>  
  11.   );  
  12. });  
  13.   
  14. function Foo({ hideFoo }) {  
  15.   return (  
  16.     <>  
  17.       <h1>Foo</h1>  
  18.       <button onClick={hideFoo}>Hide Foo</button>  
  19.     </>  
  20.   );  
  21. }  
  22.   
  23. function App() {  
  24.   const [isFooVisible, setFooVisibility] = useState(false);  
  25.   
  26.   return (  
  27.     <div className="App">  
  28.       {isFooVisible ? (  
  29.         <Foo hideFoo={() => setFooVisibility(false)} />  
  30.       ) : (  
  31.         <button onClick={() => setFooVisibility(true)}>Show Foo</button>  
  32.       )}  
  33.       <Bar name={{ first: "John", last: "Schilling" }} />  
  34.     </div>  
  35.   );  
  36. }  
  37.   
  38. const rootElement = document.getElementById("root");  
  39. ReactDOM.render(<App />, rootElement);  

尽管 Bar 做了记忆化且 props 值并没有发生变动,每次父组件重新渲染时它仍然会重新渲染。这是因为尽管每次比较的两个对象拥有相同的值,引用并不同。

函数 props 的问题

我们也可以把函数作为 props 向组件传递,当然,在 JavaScript 中函数也会传递引用,因此浅比较也是基于其传递的引用。

因此,如果我们传递的是箭头函数(匿名函数),组件仍然会在父组件重新渲染时重新渲染。

Tip #4:更好的 props 写法

前面的问题的一种解决方法是改写我们的 props。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读