React w / hooks: предотвращение повторного рендеринга компонента с помощью функции prop - PullRequest
0 голосов
/ 13 февраля 2019

Допустим, у меня есть:

const AddItemButton = React.memo(({ onClick }) => {
  // Goal is to make sure this gets printed only once
  console.error('Button Rendered!');
  return <button onClick={onClick}>Add Item</button>;
});

const App = () => {
  const [items, setItems] = useState([]);

  const addItem = () => {
    setItems(items.concat(Math.random()));
  }

  return (
    <div>
      <AddItemButton onClick={addItem} />
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
    </div>
  );
};

Каждый раз, когда я добавляю элемент, <AddItemButton /> перерисовывается, потому что addItem - новый экземпляр.Я пытался запоминать addItem:

 const addItemMemoized = React.memo(() => addItem, [setItems])

Но это повторное использование setItems с первого рендеринга, в то время как

 const addItemMemoized = React.memo(() => addItem, [items])

Не запоминает, поскольку items изменение ссылки.

Я могу сделать

 const addItem = () => {
   items.push(Math.random());
   setItems(items);
 }

Так как это не меняет ссылку на items и ничего не обновляется.

Один странный способ сделать это:

  const [, frobState] = useState();
  const addItemMemoized = useMemo(() => () => {
    items.push(Math.random());
    frobState(Symbol())
  }, [items]);

Но мне интересно, есть ли лучший способ, который не требует дополнительных ссылок на состояние.

1 Ответ

0 голосов
/ 13 февраля 2019

Текущий предпочтительный маршрут - useCallback, что совпадает с вашим решением useMemo, но с дополнительной возможной оптимизацией в будущем.Передайте пустой массив [], чтобы убедиться, что функция будет всегда иметь одинаковые ссылки для времени жизни компонента.

Здесь вы также хотите использовать функциональное состояние обновите форму , чтобы убедиться, что элемент всегда добавляется в зависимости от текущего состояния.

  const addItem = useCallback(() => {
    setItems(items => [...items, Math.random()]);
  }, []);
...