微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

更新大列表的一个元素而不在反应钩子中重新渲染其他元素?

如何解决更新大列表的一个元素而不在反应钩子中重新渲染其他元素?

我想通过测试大量的 li 来优化我的 React 应用程序 它是一个简单的待办事项列表。

例如,当点击 li 时,任务将是线状的,并且检查图标将是绿色的。这个简单的操作对于一个大列表来说非常慢,因为整个列表都被重新渲染。

如何使用 React Hooks 做到这一点?

function App() {
  const [list,setList] = useState([]);
  const [input,setInput] = useState("");

  const inputRef = useRef(null);
  useEffect(() => inputRef.current.focus(),[]);

//Pseudo Big List
  useEffect(() => {
    const test = [];
    let done = false;
    for (let i = 0; i < 5000; i++) {
      test.push({ task: i,done });
      done = !done;
    }
    setList(test);
  },[]);

  const handlerSubmit = (e) => {
    e.preventDefault();

    const newTask = { task: input,done: false };
    const copy = [...list,newTask];

    setList(copy);
    setInput("");
  };

  const checkHandler = (e,index) => {
    e.stopPropagation();
    const copy = [...list];
    copy[index].done = !copy[index].done;
    setList(copy);
  };

  const suppression = (e,index) => {
    e.stopPropagation();
    const copy = [...list];
    copy.splice(index,1);
    setList(copy);
  };

  const displayList = () => {
    return (
      <ul>
        {list.map((task,index) => (
          <Li
            key={index}
            task={task}
            index={index}
            suppression={suppression}
            checkHandler={checkHandler}
          />
        ))}
      </ul>
    );
  };

  //JSX
  return (
    <div className='App'>
      <h1>Todo JS-REACT</h1>

      <form id='form' onSubmit={handlerSubmit}>
        <input
          type='text'
          placeholder='Add task'
          required
          onChange={(e) => setInput(e.target.value)}
          value={input}
          ref={inputRef}
        />
        <button type='submit'>
          <i className='fas fa-plus'></i>
        </button>
      </form>

      {list.length === 0 && <div id='noTask'>No tasks...</div>}

      <displayList />
    </div>
  );
}

export default App;

锂组件

import React from "react";

export default function Li(props) {
  return (
    <li
      onClick={(e) => props.checkHandler(e,props.index)}
      className={props.task.done ? "line-through" : undefined}
    >
      {props.task.task}
      <span className='actions'>
        <i className={`fas fa-check-circle ${props.task.done && "green"}`}></i>
        <i
          className='fas fa-times'
          onClick={(e) => props.suppression(e,props.index)}
        ></i>
      </span>
    </li>
  );
}

此处的 CodeSandBoxhttps://codesandbox.io/s/sad-babbage-kp3md?file=/src/App.js

解决方法

您可以使用 React.memo 并包装 Li 组件。这将基于浅比较缓存 Li 组件的实例。在 docs

中了解更多信息

否则,如果您不需要容器中的状态,您可以将它本地保存在 Li 组件中,这样就不会导致整个列表重新渲染。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。