Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-router-dom v6 useNavigate passing value to another component

The version of react-router-dom is v6 and I'm having trouble with passing values to another component using Navigate.

I want to pass selected rows to another page called Report. But, I'm not sure I'm using the right syntax for navigate method and I don't know how to get that state in the Report component.

Material-ui Table: I'm trying to use redirectToReport(rowData) in onClick parameter.

function TableRows(props){
return (
    <MaterialTable
        title="Leads"
        columns={[
            ...
        ]}
        data = {props.leads}       
        options={{
            selection: true,
            filtering: true,
            sorting: true
        }}
        actions = {[{
            position: "toolbarOnSelect",
            tooltip: 'Generate a report based on selected leads.',
            icon: 'addchart',
            onClick: (event, rowData) => {
                console.log("Row Data: " , rowData)
                props.redirect(rowData)
            }
        }]}
    />
)}

LeadTable component

export default function LeadTable(props) {
let navigate = useNavigate();

const [leads, setLeads] = useState([]);
const [loading, setLoading] = useState(true);    

async function fetchUrl(url) {
    const response = await fetch(url);
    const json = await response.json();

    setLeads(json[0]);
    setLoading(false);
}

useEffect(() => {
    fetchUrl("http://localhost:5000/api/leads");
}, []);

function redirectToReport(rowData) {
    navigate('/app/report', { state: rowData }); // ??? I'm not sure if this is the right way
}

return(
    <div>
        <TableRows leads={leads} redirect={redirectToReport}></TableRows>
    </div>
)}

Report component

export default function ReportPage(state) {
return (
    <div>
        { console.log(state) // This doesn't show anything. How to use the state that were passed from Table component here?}
        <div className = "Top3">
          <h3>Top 3 Leads</h3>
            <ReportTop3 leads={[]} />
        </div>
    </div>
);}
like image 254
Jay Kim Avatar asked Oct 28 '20 04:10

Jay Kim


People also ask

How do you use useNavigate in react dom v6 router?

Step 1: To start with, create a React application using the following command: npx create-react-app <project_name>; Step 2: Install the latest version of react-router-dom in the React application by the following. Project Structure: Create a folder named components in the src folder and add files Home.

What does useNavigate return?

The useNavigate hook returns a function that lets you navigate programmatically, for example after a form is submitted. If using replace: true , the navigation will replace the current entry in the history stack instead of adding a new one.

How to use usenavigate passing value to another component with react-router-Dom V6?

To use useNavigate passing value to another component with react-router-dom v6, we can call navigate with an object as the 2nd argument. ← How to fix the “Cannot read property ‘push’ of undefined” error with React Router? → How to test components using React Router hooks with Jest?

Is it possible to use navigate in react router V6?

See e.g. stackoverflow.com/q/53371356/3001761, this isn't specific to React Router. In the react-router-dom v6, the support for history has been deprecated but instead of it, navigate has been introduced.

How to navigate in a react class component?

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. This answer seems appropriately clear and sufficient to addressing the question.

How does react router work?

In React, the page contents are created from our components. So what React Router does is intercept the request being sent to the server and then injects the contents dynamically from the components we have created.


Video Answer


4 Answers

version 6 react-router-dom

I know the question got answered but I feel this might be helpful example for those who want to use functional components and they are in search of passing data between components using react-router-dom v6.

Let's suppose we have two functional components, first component A, second component B. The component A wants to share data to component B.

usage of hooks: (useLocation,useNavigate)


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

function ComponentA(props) {

  const navigate = useNavigate();

  const toComponentB=()=>{
navigate('/componentB',{state:{id:1,name:'sabaoon'}});
  }

  return (
   <>
<div> <a onClick={()=>{toComponentB()}}>Component B<a/></div>
</>
  );


}


export default ComponentA;

Now we will get the data in Component B.

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

 function ComponentB() {

    const location = useLocation();
   
        return (

            <>
               
<div>{location.state.name}</div>

            </>
        )
    }

export default ComponentB;

Note: you can use HOC if you are using class components as hooks won't work in class components.

like image 56
Sabaoon Bedar Avatar answered Oct 22 '22 04:10

Sabaoon Bedar


Your navigate('/app/report', { state: rowData }); looks correct to me.

react-router-v6

If you need state, use navigate('success', { state }).

navigate

interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: any }
  ): void;
  (delta: number): void;
}

Your ReportPage needs to be rendered under the same Router that the component doing the push is under.

Route props are no longer passed to rendered components, as they are now passed as JSX literals. To access route state it must be done so via the useLocation hook.

function ReportPage(props) {
  const { state } = useLocation();
  console.log(state);

  return (
    <div>
      <div className="Top3">
        <h3>Top 3 Leads</h3>
        <ReportTop3 leads={[]} />
      </div>
    </div>
  );
}

If the component isn't able to use React hooks then you still access the route state via a custom withRouter Higher Order Component. Here's an example simple withRouter HOC to pass the location as a prop.

import { useLocation, /* other hooks */ } from 'react-router-dom'; 

const withRouter = WrappedComponent => props => {
  const location = useLocation();
  // other hooks

  return (
    <WrappedComponent
      {...props}
      {...{ location, /* other hooks */ }}
    />
  );
};

Then access via props as was done in pre-RRDv6.

class ReportPage extends Component {

  ...

  render() {
    console.log(this.props.location.state);

    return (
      <div>
        <div className="Top3">
          <h3>Top 3 Leads</h3>
          <ReportTop3 leads={[]} />
        </div>
      </div>
    );
  }
}
like image 33
Drew Reese Avatar answered Oct 22 '22 03:10

Drew Reese


2 things (just a suggestion): Rather than a ternary use &&

{location && <div>{location.state.name}</div>}

Why are you checking location and rendering location.state.name? I would use the check on the data you are fetching or make sure the data returns null or your value.

like image 40
David Fischer Avatar answered Oct 22 '22 04:10

David Fischer


On Sabaoon Bedar's Answer, you can check if there is any data or not before showing it :

  • Instead of this <div>{location.state.name}</div>

  • Do this { location != null ? <div>{location.state.name}</div> : ""}

like image 22
S3D Avatar answered Oct 22 '22 04:10

S3D