Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 332
Anetellie Avatar asked Jun 04 '26 12:06

Anetellie


2 Answers

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.

like image 128
Anthony Garcia-Labiad Avatar answered Jun 07 '26 02:06

Anthony Garcia-Labiad


In react-router-dom latest version(v6) you cannot use this.props.match.params.id and this.props.history (in react latest vesion history replace with navigate). Besides you cannot call them in class component. To call them in class component make a function first -

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

    export function withParamsAndNavigate(Component) {
      return (props) => (
       <Component {...props} params={useParams()} navigate={useNavigate()} />
  );
}
  • I want to use it for ProductDetails component. That's given below -

     import { withParamsAndNavigate } from "./getParamsAndNavigate.js";
    
     class ProductDetails extends React.Component {
      state = {//}
    
    render() {
     const{params,navigate} = this.props;
      // params.id - will return the id,
      // navigate('yourUrl') - will redirect the target url.
      return (
         //
       );
      }
     }
    
    export default withParamsAndNavigate(ProductDetails);
    
  • Here is my App module where I defined my routes -

         import React from "react";
         import { Routes, Route} from "react-router-dom";
         import Product from "./components/Product";
         import ProductDetails "./components/ProductDetails";
    
         function App() {
           return (
               <div>
                  <main role='main' className='container'>
                    <Routes>
                       <Route path='/product' element={<Product />} />
                       <Route path="/product/:id"} element={<ProductDetails />} />
                    </Routes>
                  </main>
              </div>
           );
          }
         export default App;
    
  • It works for me and hope it will help you.

like image 43
Mahadi Hassan Babu Avatar answered Jun 07 '26 01:06

Mahadi Hassan Babu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!