admin管理员组文章数量:1279186
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:
- When the props consist of only
onChange
and no other elements, is theuseCallback
unnecessary in this case, since the entire ponent is already memo-ed based ononChange
? - If we add an additional prop (say a
value
for the initial value for the<input>
), then I thinkuseCallback
bees useful, since otherwisehandleChange
will be recreated even ifonChange
doesn't change butvalue
is changed. Is that correct?
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:
- When the props consist of only
onChange
and no other elements, is theuseCallback
unnecessary in this case, since the entire ponent is already memo-ed based ononChange
? - If we add an additional prop (say a
value
for the initial value for the<input>
), then I thinkuseCallback
bees useful, since otherwisehandleChange
will be recreated even ifonChange
doesn't change butvalue
is changed. Is that correct?
2 Answers
Reset to default 11When the props contains only
onChange
and no other elements, is theuseCallback
unnecessary in this case, since the entire ponent is already memo-ed based ononChange
?
It's memoized based on all props, not just onChange
. Yes, useCallback
is unnecessary there.
If we add an additional prop (say a
value
for the initial value for the<input>
), then I thinkuseCallback
bees useful, since otherwisehandleChange
will be recreated even ifonChange
doesn't change but value is changed. 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). E.g.:
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.
You might not keep React.memo
in that case, if you're expecting that value
will get changed as a result of the onChange
. That is, if you expect the mon case to be that value
will be different each time your ponent is called, then React.memo
's check of the props is extra work you might not keep:
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.
If you just want to supply the initial value to your ponent 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
:
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. 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:
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 ponent function is called, even when you're using useCallback
. It has to be, so it can be passed into useCallback
as an argument. The only difference is whether you use that new function, or the original one that was created the first time (the result of 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 ponents.
When the props consist of only
onChange
and no other elements, is theuseCallback
unnecessary in this case, since the entire ponent is already memo-ed based on onChange?
No, it might be necessary, memo
and useCallback
don't serve the same purpose.
Without useCallback
you may have "heavy putation" on every render:
"heavy putation" refers to a generic case and not to this specific example where you only pass the event's value.
const UserInput = React.memo(({ onChange = () => {} }) => {
// Unment for memoization
// Note that you can implement useCallback with useMemo
// const handleChange = useMemo(() => {
// console.log("heavy putation memoized");
// return event => {
// onChange(event.target.value);
// };
// }, [onChange]);
const handleChange = event => {
// Here we can have some heavy putation
// Not related to this specific usecase
console.log("heavy putation 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
bees useful, since otherwisehandleChange
will be recreated even if onChange doesn't change but value is changed. Is that correct?
If you are going to use controlled ponent (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?):
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} />;
};
本文标签: javascriptuseCallback necessary within ReactmemoStack Overflow
版权声明:本文标题:javascript - useCallback necessary within React.memo? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741252671a2366084.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论