[英]Exceeding update depth with userReducer but not with useState
我有一個 useEffect 每次用戶在輸入中鍵入內容時觸發。 起初我讓它使用 useState 運行,它運行得像黃油一樣順暢,但我需要將它更改為 useReducer。 useEffect 和 useReducer:
useEffect(() => {
dispatch({type : 'username', payload : watch().username});
dispatch({type : 'password', payload : watch().password});
console.log(state.username, state.password);
}, [watch()]);
帶有 useState 的 useEffect:
useEffect(() => {
setPassword(watch().password);
setUsername(watch().username);
console.log(username, password);
}, [watch()]);
即使用戶沒有輸入任何內容,useEffect 也會不斷被觸發,因為與 useState 一起使用時它不會那樣做。
減速機:
const reducer = (state, action) => {
switch (action.type) {
case "username":
return {...state, username: action.payload };
case "password":
return {...state, password : action.payload};
}
};
這里有一些危險信號,但最突出的是你如何使用watch()
。 useEffect
和useState
將(可能)在每次渲染時重新運行,因為watch()
可能返回一個非記憶的 object。 您的代碼使用useState
“工作”的原因是因為將 state object 設置為同樣的事情沒有任何作用- 如果用戶名或密碼沒有改變,則 state 不會重新渲染。
但是,對於useReducer
,情況並非如此,除非您在減速器 function 中明確地滿足它 - 這樣的事情可能會修復錯誤:
const reducer = (state, action) => {
switch (action.type) {
case "username":
return state.username !== action.payload
? {...state, username: action.payload }
: state;
case "password":
return state.password !== action.payload
? {...state, password: action.payload }
: state;
default:
return state;
}
};
但是,您還應該嘗試使掛鈎的依賴關系盡可能簡單。 有什么理由你不能先調用watch()
,然后將值傳遞給你的效果嗎?
const { username, password } = watch();
useEffect(() => {
dispatch({type : 'username', payload : username});
dispatch({type : 'password', payload : password});
}, [username, password]);
或者,您可以更好地使用 go 並將兩者分成兩種不同的效果 - 如果password
已更改,則無需發送username
更新:
const { username, password } = watch();
useEffect(() => {
dispatch({type : 'username', payload : username});
}, [username]);
useEffect(() => {
dispatch({type : 'password', payload : password});
}, [password]);
而且,當我們處於重構模式時,為什么不創建一個自定義掛鈎來為您處理邏輯呢? 就像是:
const useLoginFormState = (formValues) => {
const { username, password } = formValues;
useEffect(() => {
dispatch({type : 'username', payload : username});
}, [username]);
useEffect(() => {
dispatch({type : 'password', payload : password});
}, [password]);
return formValues;
}
// Now in your component -
const MyComponent = () => {
const formValues = useLoginFormState(watch());
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.