[英]useCallback necessary within React.memo?
考虑这个例子:
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;
我的问题是:
onChange
而没有其他元素时,在这种情况下是否不需要useCallback
,因为整个组件已经基于onChange
进行了备忘录?<input>
的初始value
的值),那么我认为useCallback
变得有用,因为否则即使onChange
没有改变但value
改变了,也会重新创建handleChange
。 那是对的吗?当 props 仅包含
onChange
而没有其他元素时,在这种情况下是否不需要useCallback
,因为整个组件已经基于onChange
进行了备忘录?
它是基于所有道具记忆的,而不仅仅是onChange
。 是的, useCallback
在那里是不必要的。
如果我们添加一个额外的道具(比如
<input>
的初始value
的值),那么我认为useCallback
变得有用,因为否则即使onChange
没有改变但值改变了,也会重新创建handleChange
。 那是对的吗?
如果你想在更新input
时更新value
而不是更新onChange
,你可以为你的 props 添加value
并继续为你的handleChange
useCallback
如果你愿意,这样 React 就不必换入新的事件处理程序当它设置值时;我的印象是这通常是矫枉过正的)。 例如:
const UserInput = React.memo(({ onChange, value }: UserInputProps) => {
const handleChange = useCallback(
(event) => {
onChange(event.target.value);
},
[onChange]
);
return <input type="text" value={value} onChange={handleChange} />;
});
如果onChange
道具没有改变,那将使用最新的value
并重用之前的handleChange
。
在这种情况下,您可能不会保留React.memo
,如果您期望该value
会因onChange
而改变。 也就是说,如果您希望每次调用组件时该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} />;
};
但是如果你希望React.memo
继续检查 props 并且在 props 都没有变化时不调用你的 function,你可以保留它。
如果你只是想为你的组件提供初始值然后在本地控制它,你可以继续使用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} />;
});
只有当onChange
或initialValue
改变时才会被调用。 您也可以在那里使用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} />;
});
旁注:要记住的一件事是,每次调用组件 function 时都会创建一个新的handleChange
function ,即使您使用的是useCallback
。 它必须是,所以它可以作为参数传递给useCallback
。 唯一的区别是您是使用新的 function,还是第一次创建的原始的( useCallback
的结果)。 我认为重用为给定的一组依赖项创建的第一个依赖项的原因是最小化传递给子组件的更改。
当 props 仅包含
onChange
而没有其他元素时,在这种情况下是否不需要useCallback
,因为整个组件已经基于 onChange 进行了备忘录?
不,可能有必要, memo
和useCallback
的目的不同。
如果没有useCallback
,您可能在每次渲染时都有“大量计算”:
“大量计算”是指一般情况,而不是仅传递事件值的特定示例。
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} />;
});
如果我们添加一个额外的道具(比如 的初始值的值),那么我认为
useCallback
变得有用,因为否则即使 onChange 没有改变但值改变了,也会重新创建handleChange
。 那是对的吗?
如果您要使用受控组件(由于使用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.