簡體   English   中英

使用 userReducer 但沒有使用 useState 超過更新深度

[英]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() useEffectuseState將(可能)在每次渲染時重新運行,因為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM