[英]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.