带钩的React:防止重新渲染具有prop功能的组件

时间:2019-02-13 00:09:43

标签: javascript reactjs react-hooks

假设我有:

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 :(得分:5)

当前的首选路由为useCallback,与您的useMemo解决方案相同,但将来还会进行其他优化。传递一个空数组[],以确保该函数在组件的整个生命周期中始终具有相同的引用。

在这里,您还想使用functional state update form,以确保始终根据当前状态添加该项。

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