How to prevent the rerenders and improve performance (Todo example with hooks)

Keywords: reactjs performance react-hooks

Question: 

I want to dig into React hooks a little bit and have been trying to figure out how to make my components more performant. Even though I think I'm using useCallback at the right place, my application feels really slow, because too many updates happen.

What could I improve so only one or two components change instead of recreating the whole thing?

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]);
}

Example (open with caution as I'm rendering 10k components): https://codesandbox.io/embed/quizzical-sun-92qnw

Answers: