React.useCallback 记忆柯里化函数了吗?
Does React.useCallback memoize curried functions?
我有时会在 useCallback
.
中声明柯里化函数时使用这种模式
const Child = ({ handleClick }) => {
return (
<>
<button onClick={handleClick("foo")}>foo</button>
<button onClick={handleClick("lorem")}>lorem</button>
</>
);
};
export default function App() {
const [state, setState] = useState("");
const handleClick = useCallback(
(newState) => () => {
setState(newState);
},
[]
);
return (
<div className="App">
<Child handleClick={handleClick} />
<p>{state}</p>
</div>
);
}
因为我想将参数从 JSX 传递到事件处理程序并避免使用多个处理程序。
当组件重新渲染时,将调用handleClick
并将返回的函数分配给onClick
prop,但每次都是新函数还是嵌套函数也被 useCallback
?
记住了
PS:这是一个简单的例子。假设 useCallback
具有多个依赖项的用法
应该吧,不管是不是curry,都是一个函数实例,只要你想保留一个旧的函数实例,都可以用。
但是不要因为属性 onClick
而使用它,因为当你的组件呈现时,这个 button
必须呈现而不管 onClick
。所以你的行可以简单地写成
const onClick = value => () => { setState(value) }
或者您甚至可以将其提升为全局函数。
const handle = setState => value => () => { setState(value) }
注意:我不想说 useCallback
大多数时间都是无用的。但实际上,如果您不知道为什么要使用 useMemo
,请不要使用 useCallback
。它们旨在跳过分配,但不是为了跳过渲染,或者在您的情况下,是为了提高可重用性。 (不是为了这个目的)。
编辑
以下答案指的是 OP 代码的 initial version,其中 handleClick
未作为道具传递给 Child
组件。
在这种情况下你并不需要 useCallback
。
实际上,在这种情况下最好不要使用 useCallback
挂钩,因为:
传递给 useCallback
的回调函数会在您的组件每次重新呈现时创建。结果,无论如何都会创建一个新函数,就像不使用 useCallback
一样
获取 handleClick
函数的记忆版本对您的情况没有任何好处。如果将 handleClick
作为 prop 传递给子组件,记忆将很有用。
...but will it be a new function every time or will the nested
function also get memoized by useCallback?
不,嵌套函数不会被记忆。
handleClick
是一个记忆函数,但那个记忆函数 returns 每次执行时都是一个新函数。
调用 handleClick
就像调用任何其他函数一样 - 每次调用时都会创建在函数体内声明的任何内容。
我有时会在 useCallback
.
const Child = ({ handleClick }) => {
return (
<>
<button onClick={handleClick("foo")}>foo</button>
<button onClick={handleClick("lorem")}>lorem</button>
</>
);
};
export default function App() {
const [state, setState] = useState("");
const handleClick = useCallback(
(newState) => () => {
setState(newState);
},
[]
);
return (
<div className="App">
<Child handleClick={handleClick} />
<p>{state}</p>
</div>
);
}
因为我想将参数从 JSX 传递到事件处理程序并避免使用多个处理程序。
当组件重新渲染时,将调用handleClick
并将返回的函数分配给onClick
prop,但每次都是新函数还是嵌套函数也被 useCallback
?
PS:这是一个简单的例子。假设 useCallback
具有多个依赖项的用法
应该吧,不管是不是curry,都是一个函数实例,只要你想保留一个旧的函数实例,都可以用。
但是不要因为属性 onClick
而使用它,因为当你的组件呈现时,这个 button
必须呈现而不管 onClick
。所以你的行可以简单地写成
const onClick = value => () => { setState(value) }
或者您甚至可以将其提升为全局函数。
const handle = setState => value => () => { setState(value) }
注意:我不想说 useCallback
大多数时间都是无用的。但实际上,如果您不知道为什么要使用 useMemo
,请不要使用 useCallback
。它们旨在跳过分配,但不是为了跳过渲染,或者在您的情况下,是为了提高可重用性。 (不是为了这个目的)。
编辑
以下答案指的是 OP 代码的 initial version,其中 handleClick
未作为道具传递给 Child
组件。
在这种情况下你并不需要 useCallback
。
实际上,在这种情况下最好不要使用 useCallback
挂钩,因为:
传递给
一样useCallback
的回调函数会在您的组件每次重新呈现时创建。结果,无论如何都会创建一个新函数,就像不使用useCallback
获取
handleClick
函数的记忆版本对您的情况没有任何好处。如果将handleClick
作为 prop 传递给子组件,记忆将很有用。
...but will it be a new function every time or will the nested function also get memoized by useCallback?
不,嵌套函数不会被记忆。
handleClick
是一个记忆函数,但那个记忆函数 returns 每次执行时都是一个新函数。
调用 handleClick
就像调用任何其他函数一样 - 每次调用时都会创建在函数体内声明的任何内容。