React 词条目录
前端Wiki/React/深入/性能优化与自定义 Hook

重渲染与 memo

  • 父更新默认连带所有子组件重渲染,memo 可拦截“props 没变”的子组件
  • memo 只做浅比较:对象/函数 props 每次新引用会让 memo 失效
  • 先测后优化:React DevTools Profiler 找到真正慢的组件再上 memo
HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>memo</title>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, memo } = React;

// memo 包住:props 不变就不重渲染
const SlowItem = memo(function SlowItem({ text }) {
  console.log('SlowItem 渲染了:', text);   // 观察控制台
  return <li>{text}</li>;
});

// 没包 memo:父组件每次渲染它都跟着渲染
function FastItem({ text }) {
  console.log('FastItem 渲染了:', text);
  return <li>{text}</li>;
}

function App() {
  const [count, setCount] = useState(0);
  return (
    <div style={{ padding: 16 }}>
      <p>count = {count}(看控制台:memo 的 SlowItem 不再重渲染)</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <ul>
        <SlowItem text="memo 子组件" />
        <FastItem text="普通子组件" />
      </ul>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
本节要点memo 拦截 props 未变的子组件重渲染;但浅比较挡不住新引用的对象/函数 props。