如何防止重新渲染并提高性能(带有钩子的待办事项示例)



我想深入研究一下 React 钩子,并一直在尝试弄清楚如何让我的组件性能更高。尽管我认为我在正确的位置使用了useCallback,但我的应用程序感觉真的很慢,因为发生了太多的更新。

我可以改进什么,以便只更改一两个组件而不是重新创建整个组件?

function createTodos(number) {
  const todos = [];
  for (let i = 0; i < number; i++) {
    todos.push({
      id: i,
      toggled: !(i % 4)
    });
  }
  return todos;
}
function Todos() {
  const [todos, setTodos] = useState(() => createTodos(10000));
  const toggleTodo = useCallback(
    id => {
      setTodos(
        todos.map(todo => {
          return todo.id === id ? { ...todo, toggled: !todo.toggled } : todo;
        })
      );
    },
    [todos]
  );
  return useMemo(
    () =>
      todos.map(todo => (
        <Todo
          key={todo.id}
          todoId={todo.id}
          toggled={todo.toggled}
          toggleTodo={toggleTodo}
        />
      )),
    [todos, toggleTodo]
  );
}
function Todo({ todoId, toggled, toggleTodo }) {
  const toggle = useCallback(() => toggleTodo(todoId), [todoId, toggleTodo]);
  return useMemo(() => {
    const style = {
      background: toggled ? "green" : "red",
      margin: 2,
      padding: 4
    };
    return (
      <div style={style} onClick={toggle}>
        {todoId}
      </div>
    );
  }, [todoId, toggled, toggle]);
}

示例(当我渲染 10k 组件时请谨慎打开(: https://codesandbox.io/embed/quizzical-sun-92qnw

要比较性能与 useReducer 解决方案,请执行以下操作:https://codesandbox.io/s/nifty-hodgkin-gdo2g

化简

器解决方案要快得多(因为当然化简器引用永远不会改变,但我在所有函数上使用 useCallback 我(作为回调传递,所以我不应该与第一个示例有相同的结果吗?

通过声明我的toggleTodo函数来解决此问题,例如:

const toggleTodo = useCallback(
    id => {
      setTodos(
        todos.map(todo => {
          return todo.id === id ? { ...todo, toggled: !todo.toggled } : todo;
        })
      );
    },
    [todos]
  );
在这种情况下,待办事项

是依赖项,每当待办事项发生变化时,它都会收到一个新的引用,并且所有内容都将重新呈现为我们的浅层引用将有所不同。

所以解决方案:

const toggleTodo = useCallback(
    id => {
      setTodos(oldTodos => 
        oldTodos.map(todo => {
          return todo.id === id ? { ...todo, toggled: !todo.toggled } : todo;
        })
      );
    },
    []
  );

我们的 useState 第二个参数可以是值或函数回调。通过使用函数回调,待办事项将不再是依赖项,我们将能够避免这些重新渲染(实际上这些不是重新渲染,而是重新计算?

相关内容

  • 没有找到相关文章

最新更新