簡體   English   中英

useCallBack react-hooks/exhaustive-deps 警告

[英]useCallBack react-hooks/exhaustive-deps warning

這是我在 React js 中的代碼的一部分:

export default function Registration() {
    const [email, setEmail] = useState(null);
    const [password, setPassword] = useState(null);
    const [passwordRepeat, setPasswordRepeat] = useState(null);
    const [isFieldsOK, setFieldsOK] = useState(false);

    useEffect(() => {
        if (checkFieldsOK()) {
            setFieldsOK(true);
        } else {
            setFieldsOK(false);
        }
    }, [checkFieldsOK])

    const checkFieldsOK = () => {
        return (isEmail(email) && isValidPassword(password) && passwordRepeat === password);
    }
}

我有 isFieldsOK state 它告訴我我的字段是否有效,我希望它“監聽”注冊 function 中的每一個更改。 運行此程序后,我收到此警告:

The 'checkFieldsOK' function makes the dependencies of useEffect Hook (at line 34) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of 'checkFieldsOK' in its own useCallback() Hook  react-hooks/exhaustive-deps

我的代碼到底有什么問題? 我應該改變什么,為什么? 謝謝!

因為您沒有將checkFieldsOK包裝在useCallback中,所以它沒有被記憶,這意味着它會在每次渲染時重新創建。 並且因為您的useEffect具有checkFieldsOK作為依賴項,所以該效果也將運行每個渲染。

正如錯誤消息所說,第一個(我認為不正確)選項是將 function 聲明移動到useEffect中,如下所示:

useEffect(() => {
    const checkFieldsOK = () => {
        return (isEmail(email) && isValidPassword(password) && passwordRepeat === password);
    }

    if (checkFieldsOK()) {
        setFieldsOK(true);
    } else {
        setFieldsOK(false);
    }
}, []);

但這意味着它只會在掛載時運行(因為依賴數組為空),因此更好的方法是將checkFieldsOK function 包裝在useCallback中,因此不會在每次重新渲染時重新制作,並且效果僅在字段時運行值變化:

const checkFieldsOK = useCallback(() => {
    return (isEmail(email) && isValidPassword(password) && passwordRepeat === password);
}, [email, password, passwordRepeat]);

在第二種useCallback方法中,它的行為如下:

  1. 字段值更改
  2. checkFieldsOK function 重新制作
  3. useEffect運行並檢查字段的驗證,根據需要更新 state

首先,我會考慮將checkFieldsOK表達式移到useEffect上方。

然后問自己, checkFieldsOK是什么時候創建的,調用的?

假設isEmailisValidPassword是在組件外部聲明的函數,要解決 linter 問題,您需要使用useCallback checkFieldsOK

const checkFieldsOK = useCallback(() => {
        return (
          isEmail(email) &&
          isValidPassword(password) &&
          passwordRepeat === password
        );
    }, [email, password, passwordRepeat])

這樣,只要emailpasswordpasswordRepeat發生變化, checkFieldsOK就會更新它的輸入。

或將checkFieldsOK移至 useEffect 並更新效果依賴項:

    useEffect(() => {

      const checkFieldsOK = () => {
        return (
          isEmail(email) && 
          isValidPassword(password) && 
          passwordRepeat === password
         );
    }
        if (checkFieldsOK()) {
            setFieldsOK(true);
        } else {
            setFieldsOK(false);
        }
    }, [email, password, passwordRepeat])

這樣,只有在 email、密碼或密碼重復 state 更改時才會觸發您的效果。

您可以進一步簡化為:

    useEffect(() => {

      const fieldsOK = 
          isEmail(email) && 
          isValidPassword(password) && 
          passwordRepeat === password
        
       setFieldsOK(fieldsOK);

    }, [email, password, passwordRepeat])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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