Home > Software engineering >  React Hooks: Instantiating state hooks on validation Error: Invalid hook call. Hooks can only be cal
React Hooks: Instantiating state hooks on validation Error: Invalid hook call. Hooks can only be cal

Time:09-21

I get the following error, not sure what am I doing wrong in instantiating the react hooks inside a arrow functionion:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

This is my code snippet: (It's a validation react js file which returns a state of errors if any, and in the calling method it's expecting another state error):

import React, {useState, useEffect} from 'react'; import axios from '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```

CodePudding user response:

make sure that all your hook (useState, useEffect...) are inside the checkUserExists function

CodePudding user response:

Are you doing const ValidateRegister = () =>{} to wrap all what you post? It seems that you are not using a react component, or you are trying to use a component as a function util, so you cant use const [errors, setErrors] = useState({}); You can create a custom hook called useCheckUserList, with the error and setError state and return the checkUserExists and the error state, and import it to your component.

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>

And in the file where you are going to use it just import the useCheckUserList, and do the following: const {errors, checkUserList} = useCheckUserList() Now you can youse the checkUserList function and errors state.

This is just an example, you can also take all your code into a custom hook and then use it in the ValidateRegister component.

CodePudding user response:

you have to pass "error and setError" to your ValidateRegister Component from where you called or import that component like:

<ValidateRegister error={error} setError={setError} />

// and take it as props in ValidateRegister component like

const ValidateRegister = ({error, setError}) => {
 //your code
 }
  • Related