【问题标题】:useCallBack react-hooks/exhaustive-deps warninguseCallBack react-hooks/exhaustive-deps 警告
【发布时间】:2021-04-15 08:11:43
【问题描述】:

这是我在 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 状态,它告诉我我的字段是否有效,我希望它“监听”注册功能中的每一个变化。运行此程序后,我收到此警告:

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

我的代码到底有什么问题?我应该改变什么,为什么? 谢谢!

【问题讨论】:

标签: reactjs react-hooks use-effect usecallback


【解决方案1】:

因为您没有将checkFieldsOK 包装在useCallback 中,所以它没有被记忆,这意味着它会在每次渲染时重新创建。而且因为您的 useEffect 具有 checkFieldsOK 作为依赖项,所以该效果也会在每次渲染时运行。

正如错误消息所说,第一个(我认为不正确)选项是将函数声明移动到 useEffect 中,如下所示:

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

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

但这意味着它只会在挂载时运行(因为依赖数组是空的),所以更好的方法是将 checkFieldsOK 函数包装在 useCallback 中,这样它就不会在每次重新渲染时都重新制作,并且仅当字段值更改时才会运行效果:

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

在第二种useCallback 方法中,它的行为如下:

  1. 字段值更改
  2. checkFieldsOK 函数被重做
  3. useEffect 运行并检查字段的验证,根据需要更新状态

【讨论】:

    【解决方案2】:

    首先,我会考虑将checkFieldsOK 表达式移到useEffect 上方。

    然后问问自己,checkFieldsOK 是什么时候创建、调用的?

    假设 isEmailisValidPassword 是在组件外部声明的函数,要解决 linter 问题,您需要用 checkFieldsOK 包装 useCallback

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

    这样checkFieldsOK 将在emailpasswordpasswordRepeat 发生变化时更新其输入。

    或者将checkFieldsOK移动到useEffect中并更新效果依赖:

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

    这样你的效果只会在电子邮件、密码或密码重复状态发生变化时触发。

    您可以进一步简化为:

        useEffect(() => {
    
          const fieldsOK = 
              isEmail(email) && 
              isValidPassword(password) && 
              passwordRepeat === password
            
           setFieldsOK(fieldsOK);
    
        }, [email, password, passwordRepeat])
    

    【讨论】:

      猜你喜欢
      • 2020-05-01
      • 2020-01-18
      • 2021-09-03
      • 1970-01-01
      • 2021-02-18
      • 2020-06-22
      • 2020-02-21
      • 1970-01-01
      • 2020-06-08
      相关资源
      最近更新 更多