用参数反应useCallback [英] React useCallback with Parameter

查看:91
本文介绍了用参数反应useCallback的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用React的 useCallback 挂钩实质上只是围绕 useMemo 的包装,该包装专门用于函数,以避免在组件的props中不断创建新的函数实例.我的问题来自何时需要将辩论传递给基于备忘录创建的回调.

Using React's useCallback hook is essentially just a wrapper around useMemo specialized for functions to avoid constantly creating new function instances within components' props. My question comes from when you need to pass an argued to the callback created from the memoization.

例如,这样创建的回调...

For instance, a callback created like so...

const Button: React.FunctionComponent = props => {
    const onClick = React.useCallback(() => alert('Clicked!'), [])
    return <button onClick={onClick}>{props.children}</button>
}

是记忆回调的一个简单示例,不需要任何外部值即可完成其工作.但是,如果我想为 React.Dipatch< React.SetStateAction> 函数类型创建通用的备注回调,则它将需要参数...例如:

is a simple example of a memoized callback and required no external values passed into it in order to accomplish its job. However, if I want to create a generic memoized callback for a React.Dipatch<React.SetStateAction> function type, then it would require arguments...for example:

const Button: React.FunctionComponent = props => {
    const [loading, setLoading] = React.useState(false)
    const genericSetLoadingCb = React.useCallback((x: boolean) => () => setLoading(x), [])

    return <button onClick={genericSetLoadingCb(!loading)}>{props.children}</button>
}

在我脑海中,这似乎与以下操作完全相同...

In my head, this seems like its the exact same as doing the following...

const Button: React.FunctionComponent = props => {
    const [loading, setLoading] = React.useState(false)
    return <button onClick={() => setLoading(!loading)}>{props.children}</button>
}

这将使记忆功能的目的失效,因为 genericSetLoadingCb(false)也会在每个渲染上都返回一个新函数,因为它仍将在每个渲染上创建一个新函数.

which would let defeat the purpose of memoizing the function because it would still be creating a new function on every render since genericSetLoadingCb(false) would just be returning a new function on each render as well.

这种理解是正确的,还是用论点描述的模式仍然保持记忆的好处?

Is this understanding correct, or does the pattern described with arguments still maintain the benefits of memoization?

推荐答案

为了下面的示例,我将使用 genericCb 函数代替 genericSetLoadingCb .

For the sake of example below I will use a genericCb function instead of genericSetLoadingCb as you have.

const genericCb = React.useCallback((param) => () => someFunction(param), [])

我们在上面所做的工作是确保函数 genericCb 在重新渲染之间保持相同.但是,每次您用这样的方法创建一个新函数时:

What we did above is ensure that function genericCb remains the same across rerenders. However, each time you create a new function out of it like this:

genericCb("someParam")

返回的函数将在每个渲染器上不同.为了确保记住返回的函数,您需要执行以下操作:

The returned function will be different on each render. To also ensure the returned function is memoized, you need something like this:

 let memoizedCb = React.useCallback(
    memoize((param) => () => someFunction(param)),
    []
  );

例如,我使用快速记忆

import memoize from "fast-memoize";

现在,如果您使用 memoizedCb("someParam")生成函数,则只要"someParam" 仍保留一样.

Now if you use memoizedCb("someParam") to generate a function, it will return same function on each render, provided "someParam" also remains the same.

仅使用没有 useCallback 的备忘录将不起作用,因为在下一次渲染时,它将像这样从新调用备忘录:

Simply using memoize without useCallback wouldn't work, as on next render it would invoke memoize from fresh like this:

let memoized = memoize(fn)
 
memoized('foo', 3, 'bar')
memoized('foo', 3, 'bar') // cache hit

memoized = memoize(fn); // without useCallback this would happen on next render 

// Now the previous cache is lost


注意:正如@Jeaf在Typescript中指出的那样,这种方法似乎会产生警告


Note: As pointed out by @Jeaf in Typescript this approach seems to produce warning

React Hook useCallback收到了一个函数,该函数的依赖项为未知.改为通过内联函数

React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead

似乎存在警告,因为 useCallback 无法看到依赖关系,因此无法警告您可能的过时关闭.在这种情况下,由用户来决定这是否是他/她的问题.

It seems the warning is there because useCallback can't see the dependencies hence can't warn you about possible stale closures. In that case it is up to the user to decide if that's a problem in his/her case.

这篇关于用参数反应useCallback的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆