如何使用 React memo


prtyaa
prtyaa 2023-12-26 17:56:03 68419
分类专栏: 资讯
  • React 的 memo API 可用于优化 React 函数组件的渲染行为。我们将首先用一个样例组件来展示问题所在,然后使用 React memo API 来解决它。

    请记得 React 中的大部分性能优化是不成熟的。React 默认情况下很快,所以当你开始感觉性能变慢时可以尝试做一些性能优化。

    注意:不要把 React 的 memo API 和 useMemo Hook 混淆了。React memo 用于把 React 组件包裹起来以防止重新渲染,而 useMemo 用于把数值记忆化。

    我们以一个 React 应用为例,它渲染一个用户列表并且可以添加新用户到此列表中。我们在这里使用了 React 的 useState Hook 来为列表增加状态:

    import React from 'react';
    import { v4 as uuidv4 } from 'uuid';
     
    const App = () => {
      const [users, setUsers] = React.useState([
        { id: 'a', name: 'Robin' },
        { id: 'b', name: 'Dennis' },
      ]);
     
      const [text, setText] = React.useState('');
     
      const handleText = (event) => {
        setText(event.target.value);
      };
     
      const handleAddUser = () => {
        setUsers(users.concat({ id: uuidv4(), name: text }));
      };
     
      return (
        <div>
          <input type="text" value={text} onChange={handleText} />
          <button type="button" onClick={handleAddUser}>
            Add User
          </button>
     
          <List list={users} />
        </div>
      );
    };
     
    const List = ({ list }) => {
      return (
        <ul>
          {list.map((item) => (
            <ListItem key={item.id} item={item} />
          ))}
        </ul>
      );
    };
     
    const ListItem = ({ item }) => {
      return <li>{item.name}</li>;
    };
     
    export default App;
    

    如果在 App, List 和 ListItem 组件的函数内增加 console.log 语句,那么你会在每次在输入框输入时都会看到这些打印的日志:

    const App = () => {
      console.log('Render: App');
     
      ...
    };
     
    const List = ({ list }) => {
      console.log('Render: List');
      return (
        <ul>
          {list.map((item) => (
            <ListItem key={item.id} item={item} />
          ))}
        </ul>
      );
    };
     
    const ListItem = ({ item }) => {
      console.log('Render: ListItem');
      return <li>{item.name}</li>;
    };

    在输入框输入后,所有的组件都会重新渲染,这是因为 App 组件更新了它的 state,默认情况下它的所有子组件会重新渲染。

    // after typing one character into the input field
     
    Render: App
    Render: List
    Render: ListItem
    Render: ListItem
    

    这是 React 提供的默认行为,大多数时候保持这种方式没什么问题,除非你的应用开始变得慢起来。

    不过一旦它开始变得卡顿,例如在用户每次输入时渲染一个巨长的用户列表,你可以使用 React 的 memo API 来记忆化函数组件。

    const List = React.memo(({ list }) => {
      console.log('Render: List');
      return (
        <ul>
          {list.map((item) => (
            <ListItem key={item.id} item={item} />
          ))}
        </ul>
      );
    });
     
    const ListItem = ({ item }) => {
      console.log('Render: ListItem');
      return <li>{item.name}</li>;
    };
    

    现在当我们在输入框填写时,只有 App 组件重新渲染,因为它是受 state 变化影响的唯一的组件。List 组件接收的是之前记忆化的 props,而那些 props 没有发生变化,因此无需再次渲染。下层的 ListItem 没有使用 React memo API,因为 List 组件已经阻止了重新渲染。

    // after typing one character into the input field
     
    Render: App

    这就是 React 的 memo 函数。看起来我们无需为 ListItem 组件调用 memo 函数。不过如果点击了按钮新增了一个用户到列表后,你会发现当前的代码输出如下:

    // after adding an item to the list
     
    Render: App
    Render: List
    Render: ListItem
    Render: ListItem
    Render: ListItem

    新增一个用户到列表后,列表发生了变化,而这会更新 List 组件。这是符合预期的行为,因为我们想渲染已有的两个用户以及这个新增的用户。但是如果只渲染新增的用户会更高效一些。

    const List = React.memo(({ list }) => {
      console.log('Render: List');
      return (
        <ul>
          {list.map((item) => (
            <ListItem key={item.id} item={item} />
          ))}
        </ul>
      );
    });
     
    const ListItem = React.memo(({ item }) => {
      console.log('Render: ListItem');
      return <li>{item.name}</li>;
    });

    再试一次,增加一个用户到列表中,使用了 React memo 函数的新代码,你会看到如下输出:

    // after adding an item to the list
     
    Render: App
    Render: List
    Render: ListItem

    只有新增的用户渲染了。所有之前的用户保持原样,因此无需重新渲染。只有受到 state 变更影响的组件才会重新渲染。

    你可能不禁会问为什么不为所有的组件使用 memo 函数,或者为什么 React 不为所有的组件默认用上 memo。

    React memo 函数在其内部需要对比之前的 props 和新的 props,用来决定是否应该重新渲染该组件。通常这个对比的计算过程比重新渲染组件的开销要更大。

    综上所述,React memo 函数在你的应用变得卡顿想要优化性能时特别有用。通常这会发生在含有大量数据的组件,例如一条数据变化后许多组件必须重新渲染海量的数据列表。

网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。

本文链接:https://www.xckfsq.com/news/show.html?id=30952
赞同 0
评论 0 条
prtyaaL3
粉丝 1 发表 2554 + 关注 私信
上周热门
Kingbase用户权限管理  2027
信刻全自动光盘摆渡系统  1757
信刻国产化智能光盘柜管理系统  1426
银河麒麟添加网络打印机时,出现“client-error-not-possible”错误提示  1028
银河麒麟打印带有图像的文档时出错  933
银河麒麟添加打印机时,出现“server-error-internal-error”  721
麒麟系统也能完整体验微信啦!  663
统信桌面专业版【如何查询系统安装时间】  639
统信操作系统各版本介绍  631
统信桌面专业版【全盘安装UOS系统】介绍  604
本周热议
我的信创开放社区兼职赚钱历程 40
今天你签到了吗? 27
信创开放社区邀请他人注册的具体步骤如下 15
如何玩转信创开放社区—从小白进阶到专家 15
方德桌面操作系统 14
我有15积分有什么用? 13
用抖音玩法闯信创开放社区——用平台宣传企业产品服务 13
如何让你先人一步获得悬赏问题信息?(创作者必看) 12
2024中国信创产业发展大会暨中国信息科技创新与应用博览会 9
中央国家机关政府采购中心:应当将CPU、操作系统符合安全可靠测评要求纳入采购需求 8

添加我为好友,拉您入交流群!

请使用微信扫一扫!