gpt4 book ai didi

javascript - 使用参数响应 useCallback

转载 作者:行者123 更新时间:2023-12-03 14:15:36 27 4
gpt4 key购买 nike

使用 React 的 useCallback hook 本质上只是 useMemo 的包装。专门用于函数,以避免在组件的 props 中不断创建新的函数实例。我的问题来自于当您需要将争论传递给从内存创建的回调时。

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

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

是内存回调的一个简单示例,不需要向其中传递任何外部值即可完成其工作。但是,如果我想为 React.Dipatch<React.SetStateAction> 创建一个通用的内存回调函数类型,那么它需要参数...例如:

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>
}

在我看来,这似乎与执行以下操作完全相同......

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

这会破坏内存函数的目的,因为自genericSetLoadingCb(false)以来它仍然会在每次渲染上创建一个新函数。也只会在每个渲染上返回一个新函数。

这种理解是否正确,或者用参数描述的模式是否仍然保留了记忆化的好处?

最佳答案

我将提供一个略有不同的用例的答案,但它仍然会回答您的问题。

动机和问题陈述

让我们考虑以下(类似于您的 genericSetLoadingCb)高阶函数 genericCb:

  const genericCb = React.useCallback(
(param) => (e) => setState({ ...state, [param]: e.target.value }),
[]
);

假设我们在以下情况下使用它,其中 Input 是使用 React.memo 创建的内存组件 :

  <Input value={state.firstName} onChange={genericCb('firstName')} />

由于 Input 是内存组件,我们希望由 genericCb('firstName') 生成的函数在重新生成时保持相同渲染,以便内存的组件不会不必要地重新渲染。

下面我们将了解如何实现这一目标。

解决方案

现在,我们在上面构造 genericCb 的方式是确保它在渲染之间保持相同(由于使用 useCallback)。

但是,每次调用 genericCb 来创建一个新函数时,如下所示:

genericCb("firstName") 

每次渲染时返回的函数仍然不同。为了确保返回的函数针对某些输入进行内存,您还应该使用一些内存方法:

  import memoize from "fast-memoize";
....

const genericCb = React.useCallback(
memoize((param) => (e) => setState({ ...state, [param]: e.target.value })),
[]
);

现在,如果您调用 genericCb("firstName") 来生成函数,它会在每次渲染时返回相同的函数,前提是 "firstName" 也保留相同

备注

正如上面评论中指出的,使用 useCallback 的解决方案似乎会产生警告(但在我的项目中没有):

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

似乎出现警告是因为我们没有将内联函数传递给useCallback。我找到的解决方案是基于 this 消除此警告github线程是使用useMemo来模仿useCallback,如下所示:

// Use this; this doesn't produce the warning anymore  
const genericCb = React.useMemo(
() =>
memoize(
(param) => (e) => setState({ ...state, [param]: e.target.value })
),
[]
);

另外,我想指出的是,仅使用 memoize 而不使用 useCallback (或更新中的 useMemo)是行不通的,因为在下一次渲染时它会调用 memoize像这样新鲜:

let memoized = memoize(fn)

memoized('foo', 3, 'bar')
memoized('foo', 3, 'bar') // cache hit

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

// Now the previous cache is lost

关于javascript - 使用参数响应 useCallback,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61255053/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com