防止复选框在React中重新渲染

3

我正在尝试根据动态返回数据渲染多个复选框,并将它们的选中状态存储在本地状态中。

然而,当生成的复选框数量较高时,性能开始下降。我注意到问题是由于每当其中任何一个复选框被选中时,所有复选框的不断重新渲染所导致的(所有复选框状态都存储在同一个对象中,具有不同的键)

以下是我的示例代码和codesandbox链接,以查看实际的性能问题(请注意选择复选框时的延迟)

export default function App() {
  const [checkboxResponse, setCheckboxResponse] = useState([]);
  const [checkboxList, setCheckboxList] = useState();
  const [checkboxStates, setCheckboxStates] = useState({});

  useEffect(() => {
    //Generate dummy data
    const dummyData = [];

    for (let i = 0; i < 1000; i++) {
      dummyData.push(i.toString());
    }

    //Set dummyData as checkbox dynamic data
    setCheckboxResponse(dummyData);
  }, []);

  useEffect(() => {

    //When checkbox is clicked, add to local checkbox states object
    const checkboxChange = key => event => {
      setCheckboxStates({ ...checkboxStates, [key]: event.target.checked });
    };

    //Check if data is available
    if (checkboxResponse) {
      const checkboxes = checkboxResponse.map(key => {
        const value = checkboxStates[key] ? checkboxStates[key] : false;

        //Render checkbox
        return (
          <FormControlLabel
            key={key}
            checked={value}
            control={
              <Checkbox
                size="small"
                value={key}
                onChange={checkboxChange(key)}
              />
            }
            label={key}
          />
        );
      });

      setCheckboxList(checkboxes);
    }
  }, [checkboxResponse, checkboxStates]);

  return (
    <div className="App">
      {checkboxList}
    </div>
  );
}

每当更改 checkboxStates 时,似乎都会重新运行 useEffect 钩子,触发所有复选框的重新渲染。
是否有可能防止 React 在状态更改时重新渲染所有复选框?还是我们必须动态地为每个复选框创建单独的状态?
非常感谢您的帮助。

CodeSandbox

1个回答

2
你可以使用 React.memo 来防止未更改的复选框重新渲染。像这样:
import React, { useState, useEffect } from "react";
import { Checkbox, FormControlLabel } from "@material-ui/core";
import "./styles.css";

export default function App() {
  const [checkboxResponse, setCheckboxResponse] = useState([]);
  const [checkboxStates, setCheckboxStates] = useState({});

  //When checkbox is clicked, add to local checkbox states object
  const checkboxChange = key => event => {
    setCheckboxStates({ ...checkboxStates, [key]: event.target.checked });
  };

  useEffect(() => {
    //Generate dummy data
    const dummyData = [];

    for (let i = 0; i < 1000; i++) {
      dummyData.push(i.toString());
    }

    //Set dummyData as checkbox dynamic data
    setCheckboxResponse(dummyData);
  }, []);

  return (
    <div className="App">
      {checkboxResponse.map(key => {
        const value = checkboxStates[key] ? checkboxStates[key] : false;

        //Render checkbox
        return (
          <FormControlLabel
            key={key}
            checked={value}
            control={<MemoCheckbox key={key} checkboxChange={checkboxChange} />}
            label={key}
          />
        );
      })}
    </div>
  );
}

const CustomCheckbox = ({ key, checkboxChange }) => (
  <Checkbox size="small" value={key} onChange={checkboxChange(key)} />
);

const MemoCheckbox = React.memo(
  CustomCheckbox,
  (prev, next) => prev.key === next.key
);


然而,当您单击复选框时,它可能仍然不够快,因为它仍然循环遍历 .map 并创建元素。
这里是关于 Memo 的 文档参考

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接