简体   繁体   English

如何在按钮单击时触发 useCallback、useMemo 或 useEffect?

[英]How to trigger useCallback, useMemo or useEffect on button click?

I've heard that declaring a function in a react component to handle clicks should be done inside a useCallback hook to avoid recreating the function every render, specially if the function is somewhat complex, like this:我听说在一个反应​​组件中声明一个 function 来处理点击应该在 useCallback 钩子内完成,以避免在每次渲染时重新创建 function,特别是如果 ZC1C425268C 有点复杂,比如这个

const handleClick = useCallback(()=>
{
  "...do a lot of calculations here that takes time"
},[]);    

<button onClick={handleClick}>
  Click me!
</button>

But I have a special case where I want the useCallback function to trigger when the button is clicked to set a state, this is what I want:但是我有一个特殊情况,我希望在单击按钮以设置 state 时触发 useCallback function,这就是我想要的:

const [state, setState] = useState();

const handleClick = useCallback(()=>
{
  const newState = "...do a lot of calculations here that takes time"
  setState( newState )
},[ when button is clicked ]);

The problem is, how do i put the "when button is clicked" on the dependency of useCallback, and, as a matter of fact, any react hook that accepts a dependency list?问题是,我如何将“单击按钮时”放在 useCallback 的依赖项上,事实上,任何接受依赖项列表的反应钩子? I could do it with some dumb variable and separating the expensive calculations that take time from the onClick function, like bellow, but I don't think this is a good aproach since I'll be wasting memory:我可以用一些愚蠢的变量来做到这一点,并将需要时间的昂贵计算与 onClick function 分开,如下所示,但我认为这不是一个好的方法,因为我会浪费 ZCD69B4957F06CD82918D7:

const [state, setState] = useState();

const [dumb, setDumb] = useState(0);

useEffect(()=>
{
  const newState = "...do a lot of calculations here that takes time"
  setState( newState )
},[ dumb ]);

<button onClick=()=>setDumb(dumb+1)>
  Click me!
</button>

The problem is, how do i put the "when button is clicked" on the dependency of useCallback问题是,我如何将“单击按钮时”放在 useCallback 的依赖项上

You don't - the dependencies should be exactly (and only) the state/props that are referenced inside the function.你不知道 - 依赖项应该是(并且只是)在 function 中引用的状态/道具。

For example, if the function was例如,如果 function 是

() => {
  setCountState(countState + 1);
  setToggledState(!toggledState);
}

then the dependencies array should be那么依赖数组应该是

[setCountState, countState, setToggledState, toggledState]

The ESLint rule exhaustive-deps helps you to automate this. ESLint 规则穷举-deps 可帮助您自动执行此操作。

For your situation, it's perfectly fine to have the above as the only dependencies - you don't want a "dumb" placeholder value or any other dependency in the dependency array.对于您的情况,将上述内容作为唯一的依赖项是完全可以的 - 您不希望在依赖项数组中出现“哑”占位符值或任何其他依赖项。


All that said:说了这么多:

declaring a function in a react component to handle clicks should be done inside a useCallback hook to avoid recreating the function every render, specially if the function is somewhat complex在一个反应​​组件中声明一个 function 来处理点击应该在 useCallback 钩子内完成,以避免在每次渲染时重新创建 function,特别是如果 ZC1C425268E68385D14AB5074C17A9 有点复杂

This isn't really the case.事实并非如此。 useCallback isn't needed or useful in 99% of situations unless the function is being passed down to other components, in my experience - which doesn't appear to be the case here.根据我的经验,除非 function 被传递给其他组件,否则在 99% 的情况下useCallback是不需要或有用的 - 这似乎不是这种情况。 (The function will be re-created every render regardless.) (无论如何,每次渲染都会重新创建 function。)

useCallback shines when there are other components that use a function (especially components you don't know about), and you want to pass down as stable a reference as possible to them, to avoid unnecessary re-renders and hook calls.当有其他组件使用useCallback (尤其是您不了解的组件)并且您希望向它们传递尽可能稳定的引用时,useCallback 会大放异彩,以避免不必要的重新渲染和挂钩调用。

useCallback doesn't prevent the creation of the function. useCallback不会阻止 function 的创建。 It only prevents you from having a new function reference every time you re-render.它只会阻止您在每次重新渲染时获得新的 function 引用。 So with useCallback , the function is re-created every render, buy useCallback gives you back an old reference from a previous function if none of the listed dependencies have updated.因此,使用useCallback ,每次渲染都会重新创建 function ,如果列出的依赖项都没有更新,则购买useCallback会为您提供以前 function 的旧参考。

const Comp = () => {
  const [state, setState] = useState([]);

  const clickHandler = useCallback((ev) => {
    setState(prevState => prevState.concat([/* something */])
  }, [setState]);

  return <button onClick={clickHandler}>Button</button>
}

I think you've got it a bit backwards.我觉得你有点倒退了。 The useCallback hook is really only useful if the returned memoized function is passed down to descendant component via props. useCallback钩子只有在返回的 memoized function 通过 props 传递给后代组件时才真正有用。 The benefit isn't that the function is heavy, but rather that the callback reference is stable and won't trigger an unnecessary rerender.好处不是 function 很重,而是回调引用是稳定的,不会触发不必要的重新渲染。

As for using a function as a button's onClick handler, it's the useCallback hook's return value that is passed to the button's onClick handler, not the other way around where you are trying to make the click event the dependency.至于使用 function 作为按钮的onClick处理程序,它是useCallback钩子的返回值,它被传递给按钮的onClick处理程序,而不是单击事件处理程序的其他方式。

Example:例子:

const clickHandler = useCallback(() => {
  // do some expensive computations
}, [...dependencies]);

...

<button type="button" onClick={clickHander}>Click Me</button>

If you aren't passing clickHandler as a prop to another React component there isn't much benefit to memoizing it.如果您没有将clickHandler作为道具传递给另一个 React 组件,那么记忆它并没有太大的好处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM