React Memo
如果组件的 props 没有更改,使用 memo 将导致 React 跳过渲染组件,可以提高性能。
React.memo() 是一个高阶函数,它与 React.PureComponent 类似,但是一个函数组件而非一个类。
本节使用 React Hook 钩子。有关 Hook 的更多信息,请参见 React Hooks 部分。
问题
在本例中,即使 todos 没有更改,Todos 组件也会重新渲染。
实例:
index.js:
import { useState } from "react";import ReactDOM from "react-dom";import Todos from "./Todos";const App = () => {const [count, setCount] = useState(0);const [todos, setTodos] = useState(["todo 1", "todo 2"]);const increment = () => {setCount((c) => c + 1);};return (<><Todos todos={todos} /><hr /><div>Count: {count}<button onClick={increment}>+</button></div></>);};ReactDOM.render(<App />, document.getElementById('root'));
Todos.js:
import { useState } from "react";import ReactDOM from "react-dom";import Todos from "./Todos";const App = () => {const [count, setCount] = useState(0);const [todos, setTodos] = useState(["todo 1", "todo 2"]);const increment = () => {setCount((c) => c + 1);};return (<><Todos todos={todos} /><hr /><div>Count: {count}<button onClick={increment}>+</button></div></>);};ReactDOM.render(<App />, document.getElementById('root'));
单击 "increment" 按钮时,Todos 组件将重新渲染。如果此组件比较复杂,则可能会导致性能问题。
解决方法
要解决此问题,我们可以使用 memo。
使用 memo 可防止 Todos 组件不必要地重新渲染。
将 Todos 组件导出装在 memo 中:
实例:
index.js:
import { useState } from "react";import ReactDOM from "react-dom";import Todos from "./Todos";const App = () => {const [count, setCount] = useState(0);const [todos, setTodos] = useState(["todo 1", "todo 2"]);const increment = () => {setCount((c) => c + 1);};return (<><Todos todos={todos} /><hr /><div>Count: {count}<button onClick={increment}>+</button></div></>);};ReactDOM.render(<App />, document.getElementById('root'));
Todos.js:
import { useState } from "react";import ReactDOM from "react-dom";import Todos from "./Todos";const App = () => {const [count, setCount] = useState(0);const [todos, setTodos] = useState(["todo 1", "todo 2"]);const increment = () => {setCount((c) => c + 1);};return (<><Todos todos={todos} /><hr /><div>Count: {count}<button onClick={increment}>+</button></div></>);};ReactDOM.render(<App />, document.getElementById('root'));
现在,TODO 组件仅在通过 Props 传递给它的 TODO 更新时重新渲染。