Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 带挂钩的React:防止使用函数作为道具重新渲染组件_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 带挂钩的React:防止使用函数作为道具重新渲染组件

Javascript 带挂钩的React:防止使用函数作为道具重新渲染组件,javascript,reactjs,react-hooks,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 = () => { co

假设我有:

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>
  );
};
但这是重用第一次渲染中的setItems,而

 const addItemMemoized = React.memo(() => addItem, [items])
由于
引用更改,因此不进行记忆

我做不到

 const addItem = () => {
   items.push(Math.random());
   setItems(items);
 }
因为这不会改变
项的引用,也不会更新任何内容

一种奇怪的方法是:

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

但我想知道是否有更好的方法不需要额外的状态引用

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

在这里,您还需要使用,以确保始终基于当前状态添加项目

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

“useCallback(fn,inputs)相当于useMemo(()=>fn,inputs)。”这就是我所做的。但是,由于项目引用因spread/concat而发生更改,因此不会被记住。在这里,您可以将
[items]
更改为
[]
,因为更新取决于以前的状态,所以它仍然可以工作。我将编辑我的答案。我认为这里的关键是在setItems中使用函数!谢谢@kingdaroYep,这样就可以了:P当然可以
  const addItem = useCallback(() => {
    setItems(items => [...items, Math.random()]);
  }, []);