[英]useCallback necessary within React.memo?
Consider this example:考虑这个例子:
import React, { useCallback } from 'react';
type UserInputProps = {
onChange: (value: string) => void;
};
const UserInput = React.memo(({ onChange }: UserInputProps) => {
// Is this `useCallback` redundant?
const handleChange = useCallback(
(event) => {
onChange(event.target.value);
},
[onChange]
);
return <input type="text" onChange={handleChange} />;
});
export default UserInput;
My questions are:我的问题是:
onChange
and no other elements, is the useCallback
unnecessary in this case, since the entire component is already memo-ed based on onChange
?onChange
而没有其他元素时,在这种情况下是否不需要useCallback
,因为整个组件已经基于onChange
进行了备忘录?value
for the initial value for the <input>
), then I think useCallback
becomes useful, since otherwise handleChange
will be recreated even if onChange
doesn't change but value
is changed.<input>
的初始value
的值),那么我认为useCallback
变得有用,因为否则即使onChange
没有改变但value
改变了,也会重新创建handleChange
。 Is that correct?When the props contains only
onChange
and no other elements, is theuseCallback
unnecessary in this case, since the entire component is already memo-ed based ononChange
?当 props 仅包含
onChange
而没有其他元素时,在这种情况下是否不需要useCallback
,因为整个组件已经基于onChange
进行了备忘录?
It's memoized based on all props, not just onChange
.它是基于所有道具记忆的,而不仅仅是
onChange
。 Yes, useCallback
is unnecessary there.是的,
useCallback
在那里是不必要的。
If we add an additional prop (say a
value
for the initial value for the<input>
), then I thinkuseCallback
becomes useful, since otherwisehandleChange
will be recreated even ifonChange
doesn't change but value is changed.如果我们添加一个额外的道具(比如
<input>
的初始value
的值),那么我认为useCallback
变得有用,因为否则即使onChange
没有改变但值改变了,也会重新创建handleChange
。 Is that correct?那是对的吗?
If you want to update value
and not update onChange
when updating the input
, you'd add value
to your props and continue to use useCallback
for your handleChange
(if you like, so that React doesn't have to swap in a new event handler when it's setting the value; my impression is that's often overkill).如果你想在更新
input
时更新value
而不是更新onChange
,你可以为你的 props 添加value
并继续为你的handleChange
useCallback
如果你愿意,这样 React 就不必换入新的事件处理程序当它设置值时;我的印象是这通常是矫枉过正的)。 Eg:例如:
const UserInput = React.memo(({ onChange, value }: UserInputProps) => {
const handleChange = useCallback(
(event) => {
onChange(event.target.value);
},
[onChange]
);
return <input type="text" value={value} onChange={handleChange} />;
});
That will use the latest value
and reuse the previous handleChange
if the onChange
prop hasn't changed.如果
onChange
道具没有改变,那将使用最新的value
并重用之前的handleChange
。
You might not keep React.memo
in that case, if you're expecting that value
will get changed as a result of the onChange
.在这种情况下,您可能不会保留
React.memo
,如果您期望该value
会因onChange
而改变。 That is, if you expect the common case to be that value
will be different each time your component is called, then React.memo
's check of the props is extra work you might not keep:也就是说,如果您希望每次调用组件时该
value
都会有所不同,那么React.memo
对 props 的检查是您可能不会保留的额外工作:
const UserInput = ({ onChange, value }: UserInputProps) => {
const handleChange = useCallback(
(event) => {
onChange(event.target.value);
},
[onChange]
);
return <input type="text" value={value} onChange={handleChange} />;
};
But you can keep it if you want React.memo
to keep checking the props and not call your function when neither prop changes.但是如果你希望
React.memo
继续检查 props 并且在 props 都没有变化时不调用你的 function,你可以保留它。
If you just want to supply the initial value to your component and then control it locally, you could continue to use React.memo
(since it still renders the same thing for the same input props), in which case you don't need useCallback
:如果你只是想为你的组件提供初始值然后在本地控制它,你可以继续使用
React.memo
(因为它仍然为相同的输入道具呈现相同的东西),在这种情况下你不需要useCallback
:
const UserInput = React.memo(({ onChange, initialValue }: UserInputProps) => {
const [value, setValue] = useState(initialValue);
const handleChange = (event) => {
setValue(event.target.value);
onChange(event.target.value);
};
return <input type="text" value={value} onChange={handleChange} />;
});
That will only get called when onChange
or initialValue
changes.只有当
onChange
或initialValue
改变时才会被调用。 You could use also useCallback
there in order to, again, only update the onChange
on the input
when the onChange
prop changes, to avoid having React remove the old handler and set the new one when just the value
changes:您也可以在那里使用
useCallback
,以便再次仅在onChange
道具更改时更新input
上的onChange
,以避免 React 删除旧处理程序并在value
更改时设置新处理程序:
const UserInput = React.memo(({ onChange, initialValue }: UserInputProps) => {
const [value, setValue] = useState(initialValue);
const handleChange = useCallback(
(event) => {
setValue(event.target.value);
onChange(event.target.value);
},
[onChange]
);
return <input type="text" value={value} onChange={handleChange} />;
});
Side note: One thing to remember is that a new handleChange
function is created every time your component function is called, even when you're using useCallback
.旁注:要记住的一件事是,每次调用组件 function 时都会创建一个新的
handleChange
function ,即使您使用的是useCallback
。 It has to be, so it can be passed into useCallback
as an argument.它必须是,所以它可以作为参数传递给
useCallback
。 The only difference is whether you use that new function, or the original one that was created the first time (the result of useCallback
).唯一的区别是您是使用新的 function,还是第一次创建的原始的(
useCallback
的结果)。 I think the reason for reusing the first one that was created for a given set of dependencies is to minimize changes passed to child components.我认为重用为给定的一组依赖项创建的第一个依赖项的原因是最小化传递给子组件的更改。
When the props consist of only
onChange
and no other elements, is theuseCallback
unnecessary in this case , since the entire component is already memo-ed based on onChange?当 props 仅包含
onChange
而没有其他元素时,在这种情况下是否不需要useCallback
,因为整个组件已经基于 onChange 进行了备忘录?
No, it might be necessary , memo
and useCallback
don't serve the same purpose.不,可能有必要,
memo
和useCallback
的目的不同。
Without useCallback
you may have "heavy computation" on every render:如果没有
useCallback
,您可能在每次渲染时都有“大量计算”:
"heavy computation" refers to a generic case and not to this specific example where you only pass the event's value.
“大量计算”是指一般情况,而不是仅传递事件值的特定示例。
const UserInput = React.memo(({ onChange = () => {} }) => {
// Uncomment for memoization
// Note that you can implement useCallback with useMemo
// const handleChange = useMemo(() => {
// console.log("heavy computation memoized");
// return event => {
// onChange(event.target.value);
// };
// }, [onChange]);
const handleChange = event => {
// Here we can have some heavy computation
// Not related to this specific usecase
console.log("heavy computation on every render");
onChange(event.target.value);
};
return <input type="text" onChange={handleChange} />;
});
If we add an additional prop (say a value for the initial value for the ), then I think
useCallback
becomes useful, since otherwisehandleChange
will be recreated even if onChange doesn't change but value is changed.如果我们添加一个额外的道具(比如 的初始值的值),那么我认为
useCallback
变得有用,因为否则即使 onChange 没有改变但值改变了,也会重新创建handleChange
。 Is that correct?那是对的吗?
If you are going to use controlled component (due to use of value
prop of input
), the initialValue
will be initialized once , so it pretty useless trying to memorize it (for what purpose?):如果您要使用受控组件(由于使用
input
的value
属性),则initialValue
将被初始化一次,因此尝试记住它是毫无用处的(出于什么目的?):
const UserInputWithValue = ({ onChange, initialValue }) => {
// initilized once, no need to memoize
const [value,setValue] = useState(initialValue);
const handleChange = useCallback(
(event) => {
setValue(event.target.value)
onChange(event.target.value);
},
[onChange]
);
// Controlled
return <input type="text" value={value} onChange={handleChange} />;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.