简体   繁体   English

useCallBack react-hooks/exhaustive-deps 警告

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

This is part of my code in React js:这是我在 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);
    }
}

I have the isFieldsOK state which tells me if my fields are valid, and I want it to "listen" to every change in the Registration function.我有 isFieldsOK state 它告诉我我的字段是否有效,我希望它“监听”注册 function 中的每一个更改。 After running this, I get this warning:运行此程序后,我收到此警告:

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

What exactly wrong with my code?我的代码到底有什么问题? What should I change and why?我应该改变什么,为什么? Thank you!谢谢!

Because you didn't wrap checkFieldsOK in useCallback it's not memoized, which means it gets recreated on every render.因为您没有将checkFieldsOK包装在useCallback中,所以它没有被记忆,这意味着它会在每次渲染时重新创建。 And because your useEffect has checkFieldsOK as a dependency, that effect will also run every render.并且因为您的useEffect具有checkFieldsOK作为依赖项,所以该效果也将运行每个渲染。

Exactly as the error message says, first (and I believe incorrect) option is to move the function declaration inside the useEffect like so:正如错误消息所说,第一个(我认为不正确)选项是将 function 声明移动到useEffect中,如下所示:

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

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

But this means it will only run on mount (since the dependency array is empty), so a better approach is to wrap the checkFieldsOK function in a useCallback so it isn't remade every re-render and the effect only gets run when the field values change:但这意味着它只会在挂载时运行(因为依赖数组为空),因此更好的方法是将checkFieldsOK function 包装在useCallback中,因此不会在每次重新渲染时重新制作,并且效果仅在字段时运行值变化:

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

In the second useCallback approach, it behaves like so:在第二种useCallback方法中,它的行为如下:

  1. Field value changes字段值更改
  2. checkFieldsOK function gets remade checkFieldsOK function 重新制作
  3. useEffect gets run and checks validation of the fields, updating state as needed useEffect运行并检查字段的验证,根据需要更新 state

Firstly I would consider moving checkFieldsOK expression above the useEffect .首先,我会考虑将checkFieldsOK表达式移到useEffect上方。

Then ask yourself, when checkFieldsOK is created, called?然后问自己, checkFieldsOK是什么时候创建的,调用的?

Assuming isEmail and isValidPassword are functions declared outside of your component, to fix the linter issue you need to either wrap the checkFieldsOK with a useCallback :假设isEmailisValidPassword是在组件外部声明的函数,要解决 linter 问题,您需要使用useCallback checkFieldsOK

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

This way the checkFieldsOK will update it's inputs whenever the email , password or passwordRepeat would change.这样,只要emailpasswordpasswordRepeat发生变化, checkFieldsOK就会更新它的输入。

or move the checkFieldsOK into the useEffect and update the effect dependencies:或将checkFieldsOK移至 useEffect 并更新效果依赖项:

    useEffect(() => {

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

This way your effect will be triggered only when email, password or passwordRepeat state changes.这样,只有在 email、密码或密码重复 state 更改时才会触发您的效果。

You could simplify further into:您可以进一步简化为:

    useEffect(() => {

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

    }, [email, password, passwordRepeat])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 反应 useEffect 带有警告的钩子 react-hooks/exhaustive-deps - React useEffect hook with warning react-hooks/exhaustive-deps 带有自定义 IntersectionObserver 钩子的 react-hooks/exhaustive-deps 警告 - react-hooks/exhaustive-deps warning with custom IntersectionObserver hook react-hooks/exhaustive-deps 警告还是无限循环? - react-hooks/exhaustive-deps warning or infinite loop? 解决 react-hooks/exhaustive-deps 警告的最佳方法 - Best way to resolve react-hooks/exhaustive-deps warning 使用 useCallback 响应无限更新循环(react-hooks/exhaustive-deps) - React infinite update loop with useCallback (react-hooks/exhaustive-deps) 是否可以通过 useCallback 避免自定义 React Hook 上的“eslint(react-hooks/exhaustive-deps)”错误? - Is it possible to avoid 'eslint(react-hooks/exhaustive-deps)' error on custom React Hook with useCallback? 遵守 react-hooks/exhaustive-deps 会导致无限循环和/或大量 useCallback() - Obeying react-hooks/exhaustive-deps leads to infinite loops and/or lots of useCallback() 设计React Hooks可以防止React-Hooks / Exhaustive-deps警告 - Designing React Hooks prevent react-hooks/exhaustive-deps warning useEffect 和 'react-hooks/exhaustive-deps' linting - useEffect and 'react-hooks/exhaustive-deps' linting 在 Gatsby 中启用 react-hooks/exhaustive-deps - Enable react-hooks/exhaustive-deps in Gatsby
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM