React Hooks:在验证时实例化状态挂钩错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用

Posted

技术标签:

【中文标题】React Hooks:在验证时实例化状态挂钩错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用【英文标题】:React Hooks: Instantiating state hooks on validation Error: Invalid hook call. Hooks can only be called inside of the body of a function component 【发布时间】:2021-11-14 16:02:24 【问题描述】:

我收到以下错误,不确定在箭头函数内实例化反应挂钩时我做错了什么:

错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用。这可能是由于以下原因之一:

    您可能有不匹配的 React 版本和渲染器(例如 React DOM) 您可能违反了 Hooks 规则 您可能在同一个应用程序中拥有多个 React 副本 有关如何调试和解决此问题的提示,请参阅 https://reactjs.org/link/invalid-hook-call。

这是我的代码 sn-p:(这是一个验证反应 js 文件,它返回一个错误状态(如果有的话),并且在调用方法中它期待另一个状态错误):

从 'react' 导入 React, useState, useEffect; 从'axios'导入axios;


    const [errors, setErrors] = useState();

    const checkUserExists = async (phone) => 

        console.log('Inside CheckUserExists')

        let isUserExist = false;

        let formData = new FormData();
        formData.append('phone', phone);

        const response = await axios.post('http://localhost:3001/doesUserExistByPhone', formData).then(response=>
            isUserExist = false;
            console.log('Success response: ', response)
        ).catch(errorResponse=>
            console.log('Error response: ', errorResponse)
            isUserExist = true;
            setErrors(
               ...errors, phone: 'User Already exist, u know?'
            )
        )
        
        return isUserExist;
        
     


    const patternName = new RegExp('^[a-zA-Z ]3,20$')
    const patternPhone =  new RegExp('^[0-9]9,10$')
    const patternEmail = new RegExp('^[a-zA-Z0-9._:$!%-]+@[a-zA-Z0-9.-]+.[a-zA-Z]$')
    const patternPassword = new RegExp('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.8,)')

    if(!values.name || !patternName.test(values.name))
        //errors.name="Please enter a valid name"
    
    if(!values.phone || !patternPhone.test(values.phone))
        //errors.phone="Please enter a valid Phone number of 9-10 digits"
    
    if(!values.email || !patternEmail.test(values.email))
        //errors.email="Please enter a valid email address"
    
    if(!values.password || !patternPassword.test(values.password))
        //errors.password="Please enter a strong password to continue. A strong password has: Atleast 8 characters in length, 2 letters in upper case, 1 special character (!@#$&*), 2 number (0-9), 3 letters in lower case"
    

    if(!values.isTermsAndConditionsAccepted)
        //errors.isTermsAndConditionsAccepted = "Please Accept the Terms and conditions"
    

    //Check if the user already exist

    if(values.phone)
          
        console.log('Inside if Values.phone is not NULL... will check if user exist...')
        checkUserExists(values.phone)

    

    console.log('Errors found before creating user: ', errors);

    return errors;
    


export default ValidateRegister```

【问题讨论】:

【参考方案1】:

确保所有的钩子(useState、useEffect...)都在 checkUserExists 函数中

【讨论】:

这对我不起作用,因为我需要在 checkUserExists 方法之外插入错误状态。我也在验证其他参数,如果有任何错误,则插入错误状态【参考方案2】:

您是否正在使用 const ValidateRegister = () => 来包装您发布的所有内容?看来您没有使用 react 组件,或者您正在尝试将组件用作函数 util,因此您不能使用 const [errors, setErrors] = useState(); 您可以创建一个名为 useCheckUserList 的自定义钩子,带有错误和 setError 状态并返回 checkUserExists 和错误状态,然后将其导入到您的组件中。

import useState from 'react'

export const useCheckUserList = () => 

  const [errors, setErrors] = useState();

    const checkUserExists = async (phone) => 

        console.log('Inside CheckUserExists')

        let isUserExist = false;

        let formData = new FormData();
        formData.append('phone', phone);

        const response = await axios.post('http://localhost:3001/doesUserExistByPhone', formData).then(response=>
            isUserExist = false;
            console.log('Success response: ', response)
        ).catch(errorResponse=>
            console.log('Error response: ', errorResponse)
            isUserExist = true;
            setErrors(
               ...errors, phone: 'User Already exist, u know?'
            )
        )
        
        return isUserExist;
        
     



    return errors, checkUserList;
    
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

在您要使用它的文件中,只需导入 useCheckUserList,然后执行以下操作: const errors, checkUserList = useCheckUserList() 现在您可以使用 checkUserList 函数和错误状态了。

这只是一个示例,您也可以将所有代码放入自定义挂钩中,然后在 ValidateRegister 组件中使用。

【讨论】:

我该怎么做?我需要创建一个类吗?我已经在箭头函数中嵌入了钩子,这还不足以作为 React 组件吗? 如果可能请举个例子? 我编辑了这篇文章,给你一个例子,希望对你有帮助【参考方案3】:

您必须将“error and setError”传递给您调用或导入该组件的 ValidateRegister 组件,例如:

<ValidateRegister error=error setError=setError />

// and take it as props in ValidateRegister component like

const ValidateRegister = (error, setError) => 
 //your code
 

【讨论】:

以上是关于React Hooks:在验证时实例化状态挂钩错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用的主要内容,如果未能解决你的问题,请参考以下文章

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 (React-hooks React-native)

错误 无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用

如何在挂钩中比较来自 react redux 状态的值

React Hooks:如何在 useEffect 中设置状态?

React-native hooks 表单验证

在 React 中使用 Hooks 实现倒数计时器