简体   繁体   中英

React navigate router v6 invalid hook call

Im trying to redirect my user when the user is logged in. but all my methods i found so far wont work. etg im trying to use useNavigate function using react router v6.

but for some reason i get the following error:

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 react-invalid-hook-call for tips about how to debug and fix this problem.

at:

/login.jsx:35
let navigate = useNavigate();

function:

PerformLogin = () => {
  let navigate = useNavigate();
  const username = this.state.username;
  const password = this.state.password;
  if (username === '') {
    console.log("please enter username");
  } else if (password === '') {
    console.log("please enter password");
  } else {
    console.log("username of login: ",this.state.username);
    axios.post(process.env.REACT_APP_DATAURL + `/login`,{ username: username, password: password },{withCredentials: true})
    .then(res => {
      res = res.data;
      console.log(res);
      console.log(res.data);
      if (res.type) {
        console.log("navigating logged in");
        navigate.push('/crime');
        //return <Navigate to="/crime" />;
      }
    })
  }
}

Q: what do i have to do to fix this and be able to redirect my user?

Edit: For react-router v6

In react-router v6 there is no withRouter nor useHistory . I would recommend to refactor your component to use hooks for the sake of simplicity, but an alternative solution is to create a wrapper component that will pass the navigate function obtained from the hook as a prop:

import { useNavigate } from 'react-router-dom';

class MyComponent extends React.Component {
  //...
    PerformLogin = () => {
        const username = this.state.username;
        const password = this.state.password;
        // ...
        this.props.navigate('/crime');
    }
}

function WithNavigate(props) {
    let navigate = useNavigate();
    return <MyComponent {...props} navigate={navigate} />
}

export default WithNavigate

useHistory is a hook and hooks can only be used inside "function" components.

However I can guess you are using it from a "class" component, since there are some this.state , so you cannot use the hook there.

Another approach that should work for you would be to wrap your component inside a withRouter :

import { withRouter } from "react-router";

class MyComponent extends React.Component {
  //...
    PerformLogin = () => {
        const history = this.props.history;
        const username = this.state.username;
        const password = this.state.password;
        // ...
    }
}

export default withRouter(MyComponent)

The withRouter will inject the history as a prop.

You can only call hooks at the top level ( https://reactjs.org/docs/hooks-rules.html ) inside a component.

Therefore, this is invalid, being it's not only in an if statement, in a promise's .then function, and also does not appear to even be a functional component, rather, just a function:

if (res.type) {
        console.log("navigating logged in");
        navigate.push('/crime');
        //return <Navigate to="/crime" />;
    }

I would instead attempt doing something like setting a flag, and then navigating based upon that flag:

  PerformLogin = () => {
        let navigate = useNavigate();
        let shouldNavigate = false;
        const username = this.state.username;
        const password = this.state.password;
        if (username === '') {
            console.log("please enter username");
        } else if (password === '') {
            console.log("please enter password");
        } else {
                  console.log("username of login: ",this.state.username);
                   axios.post(process.env.REACT_APP_DATAURL + `/login`,{ username: username, password: password },{withCredentials: true})
      .then(res => {
          res = res.data;
        console.log(res);
        console.log(res.data);
        if (res.type) {
            console.log("navigating logged in");
            shouldNavigate = true;
            //return <Navigate to="/crime" />;
        }
        
        
      })
              
  
        }
        
        navigate.push(shouldNavigate ? '/crime' : currentURL);
  }

But I would avoid this altogether and simply utilize the useHistory hook to get an instance of history and work on that (I haven't tested this either but it should work):

  PerformLogin = () => {
        const history = useHistory();
        const username = this.state.username;
        const password = this.state.password;
        if (username === '') {
            console.log("please enter username");
        } else if (password === '') {
            console.log("please enter password");
        } else {
                  console.log("username of login: ",this.state.username);
                   axios.post(process.env.REACT_APP_DATAURL + `/login`,{ username: username, password: password },{withCredentials: true})
      .then(res => {
          res = res.data;
        console.log(res);
        console.log(res.data);
        if (res.type) {
            console.log("navigating logged in");
            history.push('/crime');
            //return <Navigate to="/crime" />;
        }
        
        
      })
              
  
        }
        
        
  }

Note: You have to do this directly in your component itself, you can't use hooks in a normal function that isn't a component.

you don't use useNavigate() in ordinary function

在此处输入图片说明

import { useParams,useNavigate } from "react-router-dom";

class MyComponent extends React.Component { // }

export function withParamsAndNavigate(MyComponent ) { return (props) =>( <MyComponent {...props} params={useParams()} navigate={useNavigate()} />); }

** const { params, navigate } = this.props;** this is for the react-router-dom latest version

*An example of how you can use.useHsitory has not been working properly in v6

import React from 'react';
import { createBrowserHistory } from 'history';


const StatusCodeCat: React.FC = () => {
//   const history = useHistory();
  const hsitory = createBrowserHistory();
  console.log(hsitory);
  


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

export default StatusCodeCat;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM