今天介绍的是避免重新渲染的 HOC(Higher Order Component) React.memo,透过它可以使我们提升 React 网站的效能。
首先,我们知道当父元件 context、state 和 props 其中之一改变时会重新渲染,底下的子元件也会跟着渲染,但实际上父元件只有 state 改变时,是没有必要渲染底下的子元件的。
而 React.memo 的功用就是避免一些不必要的渲染,透过 React.memo 包住子元件,它会记录之前的 props 内容,只有当记忆中的 props 改变时(但 state、context 不变)才会重新渲染元件。
React.memo(Component, [areEqual(prevProps, nextProps)]);
React.memo 共接收两个参数,第一个是要包住的元件,第二个是可以自订比较 props 的方法,回传 false 时会重新渲染元件。
React.memo 可惜的是它和 JS 一样也是透过 by value & by reference 去判断两个比较的值是否一样,也可以说是 shallow compare,所以当 props 是物件型别时,比较的是记忆体位置(by reference)。
父元件重新渲染时,重新提供新的 props 给子元件,如果是物件型别的话,即使内容的值完全一样,但还是会导致 memo 失效,重新渲染子元件。
此原因也是使用 useMemo 的其中一个原因
首先在 App.jsx 内设定好要传递的 props,这里刻意将不会在子元件用到的 step 和 count 传入,用来示范 React.memo 的第二个参数作用。
App.jsx
import React, { useState } from "react";
import Child from "./Child";
import ChildMemo from "./ChildMemo";
const App = () => {
const [step, setStep] = useState(0);
const [count, setCount] = useState(0);
const [number, setNumber] = useState(0);
return (
<>
<button onClick={() => setStep(step + 1)}>step is : {step} </button>
<button onClick={() => setCount(count + 1)}>count is : {count} </button>
<button onClick={() => setNumber(count + step)}>
number is : {number}
</button>
<hr />
<Child step={step} count={count} number={number} /> <hr />
<ChildMemo step={step} count={count} number={number} />
</>
);
};
export default App;
在 Child.jsx,不使用 React.memo,所以点击 step 和 count 按钮改变 state 都会导致 re-render
Child.jsx
import React from "react";
export default (props) => {
console.log(`Child re-render`);
return <p>number is : {props.number}</p>;
};
在 ChildMemo.jsx 中,将元件用 memo 包覆,并自定义了 props 比较的方法 isEqual,不管怎麽点击 step 和 count 按钮 isEqual 都会回传 false,只有当 number 更新时才 re-render。
ChildMemo.jsx
import React, { memo } from "react";
const isEqual = (prevProps, nextProps) => {
if (prevProps.number !== nextProps.number) {
return false;
}
return true;
};
export default memo((props) => {
console.log(`ChildMemo re-render`);
return <p>number is : {props.number}</p>;
}, isEqual);
<<: [ Day 06 ] Function Component
今晚我想来点... 麻而不辣的 linker script [叮咚] 您的外送餐点到瞜, 已经依照您...
目标 今天要来做的是打地鼠 Step1 const holes = document.querySe...
这边是我在上次面试时有被问到跟自己想搞清楚的几个问题 第一个问题就是什麽是MVVM? 如果VIEW上...
今天是最後一天,咱们今天不看程序码,来谈谈现在我们已经学习了 JavaScript,做个总结顺便想想...
今天我们把tableView做更新 func updateData(){ users = [] le...