Javid
Javid

Reputation: 439

How to use react-router-dom v6 navigate in class component

I installed react-router-dom v6 and I want to use a class based component, in previous version of react-router-dom v5 this.props.history() worked for redirect page after doing something but this code not working for v6 .

In react-router-dom v6 there is a hook useNavigate for functional component but I need to use it in class base component , Please help me how to use navigate in class component ?

Upvotes: 31

Views: 36176

Answers (8)

Marc
Marc

Reputation: 734

In a react class component use <Navigate>. From the react router docs:

A <Navigate> element changes the current location when it is rendered. It's a component wrapper around useNavigate, and accepts all the same arguments as props.

Upvotes: 6

Dmitry Krutkin
Dmitry Krutkin

Reputation: 139

If you need to use params for data fetching, writing a logic in your ClassComponent and render component depending on them, then create wrapper for your ClassComponentContainer

import { useLocation, useParams } from 'react-router-dom';
import ClassComponentContainer from './ClassComponentContainer';

export default function ClassComponentWrap(props) {
 const location = useLocation();
 const params = useParams();

 return <ClassComponentContainer location={location} params={params} />
}

after it just use params in ClassComponent which is in props

import React from 'react';
import { connect } from 'react-redux';
import axios from 'axios';
import PresentationComponent from './PresentationComponent';

class ClassComponent extends React.Component {
 componentDidMount() {
  let postID = this.props.params.postID;
  axios.get(`https://jsonplaceholder.typicode.com/posts/${postID}`)
       .then((response) => {console.log(response)})
 }
 render() {
  return <PresentationComponent {...this.props} />
 }
}

const mapStateToProps = (state) => {...}
const mapDispatchToProps = (dispatch) => {...}

const ClassComponentContainer = connect(mapStateToProps, mapDispatchToProps)(ClassComponent);

export default ClassComponentContainer;

and use ClassComponentWrap component in Route element attribute

import { BrowserRouter, Route, Routes } from "react-router-dom";
import ClassComponentWrap from './components/ClassComponentWrap';

export default function App(props) {
 return (
  <BrowserRouter>
   <Routes>
    <Route path="/posts/:postID?" element={<ClassComponentWrap />} />
   </Routes>
  </BrowserRouter>
 );
}

Upvotes: 0

PMArtz
PMArtz

Reputation: 146

Found this explanation from the GitHub react-router issue thread, this explained how to use react-router 6 with class components https://github.com/remix-run/react-router/issues/8146

I got this code from the above issue explanation

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

export const  withNavigation = (Component : Component) => {
  return props => <Component {...props} navigate={useNavigate()} />;
} 

//classComponent  
class LoginPage extends React.Component{

submitHandler =(e) =>{
    //successful login 
    this.props.navigate('/dashboard');
  }
}
 export default withNavigation(LoginPage);

Upvotes: 0

Marco Fernandes
Marco Fernandes

Reputation: 47

Here is my solution:

import React, { Component } from "react";
import { useNavigate } from "react-router-dom";
class OrdersView extends Component {
    Test(props){
      const navigate = useNavigate();
      return(<div onClick={()=>{navigate('/')}}>test{props.test}</div>);
    }
  render() {
    return (<div className="">
              <this.Test test={'click me'}></this.Test>
            </div>);
  }
}

Upvotes: -2

bement nikodimos
bement nikodimos

Reputation: 1

Try creating a reusable functional Component like a simple button and you can use it in your class component.

import React from "react";
import { useNavigate } from "react-router-dom";

const NavigateButton = ( { buttonTitle, route,isReplaced}) => {
    const navigate = useNavigate();
    return (
        <button 
            className = "btn btn-primary" 
            onClick = { () => { 
                navigate( route , {replace:isReplaced} )
            }}
        >
            {buttonTitle}
        </button>;
        );

    });
export default NavigateButton;

After this, you can use NavigateButton in any of your class Components. And it will work.

<NavigateButton title = {"Route To"} route = {"/your_route/"} isReplaced = {false}/>

Upvotes: 0

Mahdi Hazrati
Mahdi Hazrati

Reputation: 101

in class base component for redirect user follow this step : first import some component like this

import { Navigate } from "react-router-dom"

now make a state for Return a boolean value like this:

state = {
    redirect:false
}

now insert Naviagate component to bottom of your component tree but use && for conditional rendring like this :

{ 
   this.state.redirect && <Navigate to='/some_route' replace={true}/>
}

now when you want redirect user to some page just make true redirect state on a line of code you want now you can see you navigate to some page :)

Upvotes: 10

Try this:

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

  export const withRouter = (Component) =>  {
    function ComponentWithRouterProp(props) {
      let location = useLocation();
      let navigate = useNavigate();
      let params = useParams();
      return (
        <Component
          {...props}
          router={{ location, navigate, params }}
        />
      );
    }
    return ComponentWithRouterProp;
  }

and just used this function, in my case:

import { withRouter } from '../utils/with-router';
import './menu-item.styles.scss';


const MenuItem = ({title, imageUrl, size, linkUrl,router}) =>(
    <div
        className={`${size} menu-item`} onClick={() => router.navigate(`${router.location.pathname}${linkUrl}`)}
    >
        <div className='background-image' 
        style={{
            backgroundImage: `url(${imageUrl})`
        }}  />

        <div className="content">
            <h1 className="title">{title.toUpperCase()}</h1>
            <span className="subtitle">SHOP NOW</span>
        </div>
    </div>
)

export default withRouter(MenuItem);

I found this solution here https://www.reactfix.com/2022/02/fixed-how-can-i-use-withrouter-in-react.html

Other solution is useNavigate, for example:

 <button onClick={() => {navigate("/dashboard");}} >
        Dashboard
  </button>

Upvotes: 7

Rohit Sharma
Rohit Sharma

Reputation: 605

In the react-router-dom v6, the support for history has been deprecated but instead of it, navigate has been introduced. If you want to redirect user to a specific page on success of a specific event, then follow the steps given below:

Create a file named as withRouter.js, and paste the code given below in this file:

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

export const withRouter = (Component) => {
  const Wrapper = (props) => {
    const navigate = useNavigate();
    
    return (
      <Component
        navigate={navigate}
        {...props}
        />
    );
  };
  
  return Wrapper;
};

Now, in whichever class based component you want to redirect the user to a specific path/component, import the above withRouter.js file there and use this.props.navigate('/your_path_here') function for the redirection.

For your help, a sample code showing the same has been given below:

import React from 'react';
import {withRouter} from '.your_Path_To_Withrouter_Here/withRouter';

class Your_Component_Name_Here extends React.Component{
    constructor(){
        super()
        this.yourFunctionHere=this.yourFunctionHere.bind(this);
    }

    yourFunctionHere()
    {
        this.props.navigate('/your_path_here')
    }

    render()
    {
        return(
            <div>
              Your Component Code Here 
            </div>
        )
    }
}

export default withRouter(Your_Component_Name_Here);

Above Code works Perfect. And this is just a small extension. If you want onclick function here is the code:

<div className = "row">
    <button className= "btn btn-primary" 
            onClick={this.yourFunctionHere}>RedirectTo</button>
</div>

Upvotes: 51

Related Questions