322quick1
322quick1

Reputation: 143

useNavigate - Invalid hook call. Hooks can only be called inside of the body of a function component

I'm using ReactJS in frontend and NodeJS in backend and I'm trying to redirect with navigate function but I'm getting the error. What should I do exactly? Where am I missing? How can I redirect if the registration form is successful?

My action:

export const signup = (formData,navigation) => async (dispatch) => {
    try {
        const { data } = await API.signUp(formData)
        dispatch({type:AUTH,payload:data})
        let navigate = useNavigate();
        navigate("/");
    } catch (error) {
        dispatch({type:SIGNUP_FAIL,payload:
        error.response && error.response.data.message ? error.response.data.message : error.message
    })
    }
}

My component:

const signUpForm = (e) => {
    e.preventDefault()
    if(!login){
        dispatch(signup(form,navigation))
    }
}

Upvotes: 4

Views: 3979

Answers (2)

Daniel Santana
Daniel Santana

Reputation: 1847

Solution:

Move your React Hook (useNavigate, useEffect, useState, etc) to the root of your function component, or else it's considered to be Breaking Rules of Hooks (see below).

Why:

Complementing @hindus post, and according to the official React Documentation Rules of Hooks, Hooks can only be called inside the body of a function component.

Code Review

Hard Fail:

export const SomeView = (props: IDefaultProps) => {
  useEffect(() => {
    const navigate = useNavigate();
    navigate(ErrorPages.Unauthorized, { replace: true });
  });

  return (
    <div>...</div>
  );
}

Success (thanks @Himdus):

export const SomeView = (props: IDefaultProps) => {
  const navigate = useNavigate(); // move to the root (outside any component function)

  useEffect(() => {
    navigate(ErrorPages.Unauthorized, { replace: true });
  });

  return (
    <div>...</div>
  );
}

About the Rules:

Breaking Rules of Hooks, stand:

Functions whose names start with use are called Hooks in React.

Don’t call Hooks inside loops, conditions, or nested functions. Instead, > > always use Hooks at the top level of your React function, before any early > returns. You can only call Hooks while React is rendering a function component:

✅ Call them at the top level in the body of a function component.

✅ Call them at the top level in the body of a custom Hook.

Upvotes: 0

hindus
hindus

Reputation: 51

You need to move the hook outside of the function:

const signUpForm = (e) => {
    let navigate = useNavigate();
    e.preventDefault()
    if(!login){
        dispatch(signup(form,navigation,navigate))
    }
}

and:

export const signup = (formData,navigation,navigate) => async (dispatch) => {
    try {
        const { data } = await API.signUp(formData)
        dispatch({type:AUTH,payload:data})
        navigate("/");
    } catch (error) {
        dispatch({type:SIGNUP_FAIL,payload:
        error.response && error.response.data.message ? error.response.data.message : error.message
    })
    }
}

Upvotes: 5

Related Questions