我有一个组件由几个其他组件组成,例如文本字段,当对文本字段进行输入时,所有其他组件都会重新呈现。我想防止重新渲染,只重新渲染实际更改的组件。我已经看到“useCallback”是执行此操作的正确方法,并且我已经看到了如何使用它。但是,我在让“useCallBack”为我的案例正常工作时遇到了一些麻烦。即使我以如下简单的方式进行设置,文本字段中输入的每个新字符都会导致按钮再次呈现。我没有看到我的错误。
See working example in sandbox.
const Button = () => {
console.log("Button Rendered!");
window.alert("Button Rendered");
return <button onClick="">Press me</button>;
};
export default function App() {
const [textInput, setTextInput] = useState("Hallo");
const onChangeInput = useCallback(
(e) => {
setTextInput(e.target.value);
},
[textInput]
);
return (
<div>
<input
type="text"
onChange={onChangeInput}
value={textInput}
/>
<Button />
</div>
);
}
我很高兴任何校准。
答案 0 :(得分:3)
useCallback
不会阻止重新渲染。 React.memo
是阻止渲染的原因。它对之前的 props 和新的 props 做一个浅层比较,如果它们相同,它会跳过渲染:
const Button = React.memo(() => {
console.log("Button Rendered!");
window.alert("Button Rendered");
return <button onClick="">Press me</button>;
});
useCallback 在这方面的唯一作用是,有时您希望将函数作为道具传递给记忆化组件。为了让 memoization 起作用,props 不需要改变,useCallback 可以帮助 props 不改变。
答案 1 :(得分:2)
我个人会避免React.memo
/ React.useRef
/ React.useCallback
。
您的示例最简单的解决方案是创建另一个组件,并用它存储状态。
例如
const Button = () => {
console.log("Button Rendered!");
window.alert("Button Rendered");
return <button onClick="">Press me</button>;
};
const TextInput = () => {
const [textInput, setTextInput] = useState("Hallo");
const onChangeInput = useCallback(
(e) => {
setTextInput(e.target.value);
},
[textInput]
);
return (
<input
type="text"
onChange={onChangeInput}
value={textInput}
/>
);
}
export default function App() {
return (
<div>
<TextInput/>
<Button />
</div>
);
}
在上面如果你改变Text,App中没有State改变,所以Button不会被重新渲染,不需要useMemo等。
您会发现 React 工作得非常好,您将组件拆分得越多,它不仅可以解决重新渲染的问题,而且可能使以后重新使用组件变得更加容易。
IOW:保持状态尽可能靠近组件,性能会随之而来。
当然,您的示例很简单,在实际应用中,您将需要处理 HOC 等问题,但这是另一个问题.. :)
答案 2 :(得分:1)
更改状态会导致重新渲染组件及其所有继承人,为了防止重新渲染某些部分,您可以使用 useMemo 来防止不必要的重新渲染...
注意:useMemo 有一些成本......所以不要过度使用它(在这个小例子中,根本不推荐使用)。
在这种情况下,如果您不需要重新渲染,您可以使用 useRef 来保存输入引用以在需要时获取该值。
例如:
const BlahBlah = () => {
const inputRef = React.useRef(undefined);
return (
<div>
<input ref={inputRef} />
<button onClick={() => console.log(inputRef.current.value)}
</div>
);
};