Javascript 每次渲染都调用useCustomHook-这有什么问题吗

Javascript 每次渲染都调用useCustomHook-这有什么问题吗,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我有一个useCustomHook,我在各种组件中使用它。为了这个例子的目的,我简化了它 看起来是这样的: export const useCustomHook = () => { const [items, setItems] = React.useState([]); const doSomething = () => { ...do stuff here } return { items, setItems, doSom

我有一个
useCustomHook
,我在各种组件中使用它。为了这个例子的目的,我简化了它

看起来是这样的:

export const useCustomHook = () => {
  const [items, setItems] = React.useState([]);

  const doSomething = () => {
       ...do stuff here
  }

  return {
    items,
    setItems,
    doSomething
  };
};
然后我在各个组件中使用它

const App = () => {
   const { items, setItems, doSomething } = useCustomHook();

   return <div>whatever</div>
}
const-App=()=>{
const{items,setItems,doSomething}=useCustomHook();
还什么
}

当这个组件被重新渲染时,我可以看到
useCustomHook
被调用。该行为按预期工作,但我想知道这是否是自定义钩子的正确用法,以及我是否可以/应该做些什么来防止每次渲染时调用钩子。

每次重新渲染时,自定义钩子的主体都会再次运行这一事实是完全正常的,在大多数情况下不会造成问题

可能成为问题的两种情况是:

  • 如果它返回的内容在其他地方使用,并且希望尽可能保持返回值为静态,以避免其他重新渲染
  • 如果你的钩子在它的身体里做了什么是一个昂贵的计算
只要有可能,都可以通过记录返回的值来修复这两个问题。例如,
doSomething
可以更改为:

  const doSomething = useCallback(() => {
       ...do stuff here
  }, [ /* dependency array */ ]);
因此,它的引用仅在必要时更改—当依赖项数组更改时

State setter函数引用已经是静态的,所以这不必担心
setItems

如果你在钩子身上做一些昂贵的事情,记住它。改变

export const useCustomHook = () => {
  const [items, setItems] = React.useState([]);

  const doSomething = () => {
       ...do stuff here
  }
  const expensiveValue = compute(items);

  return {
    items,
    setItems,
    doSomething,
    expensiveValue
  };
};


当钩子再次运行时,您是否遇到了一个特殊的问题?这就是钩子的工作方式,它们在每个渲染中的调用顺序与定义的顺序相同。运行每个渲染时是否存在任何特定问题?我认为这仍然取决于您所说的“再次运行”。如果将console.log放入此
useCustomHook
,则会再次运行。但在您的代码中,并非所有内容都是。例如,
[]
不会再次传入初始值。如果您使用
useCallback
useMoom
也会看到某些东西不会再次运行。这不是什么问题,但注意到它一直被调用,但一切都按预期进行@CertainPerformance@windmaomao我确实考虑过使用useCallback或useMemo,但我发现在它们内部不能使用钩子。
export const useCustomHook = () => {
  const [items, setItems] = React.useState([]);

  const doSomething = () => {
       ...do stuff here
  }
  const expensiveValue = useMemo(() => compute(items), [items]);

  return {
    items,
    setItems,
    doSomething,
    expensiveValue
  };
};