Home > Back-end >  React-Router - How to show data passed from one component to another using useNavigate or Link and u
React-Router - How to show data passed from one component to another using useNavigate or Link and u

Time:10-23

I'm basically trying to show some data in one of my components. The data is passed from my main page but I can't get it to work using useLocation.

I'm getting the data from my firebase db.

My main page is a job board and I want users to be able to click on the job card and go to a new page with all the details of that job.

I see on the console that I get the data but I can't seem to display it in my component/page. I get undefined when doing console.log

See below for more details:

Jobs.js

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

export default () => {
  const navigate = useNavigate();
  const [jobs, setJobs] = useState([]);


  return (
    <div>
      {jobs.map(job => {
        return (
          <div key={job.id}>

            //My attempt using Link
            <Link
              to={`/view-contact-details/${job.id}`}
              state={{jobs}}
            >
              <button>View</button>
            </Link>

            //My attempt using useNavigate
            <button onClick={() => {
                navigate(`/view-contact-details/${job.id}`, { state:{ jobs } });
              }}
            >
              Go To Job details 
            </button>
          </div>
        );
      })}
    </div>
  );
};

App.js

import React from "react";
import Jobs from "./pages/jobs"
import Form from "./pages/form"
import { Routes, Route } from "react-router-dom"
import ViewUserDetails from "./components/Job/ViewJobDetails";

export default () => {
  return (
    <div className="App">
      <Routes>
        <Route exact path='/' element={<Jobs/>} />
        <Route exact path='/form' element={<Form/>} />
        <Route
          exact
          path="/view-contact-details/:id"
          element={<ViewJobDetails/>}
        />
      </Routes>
    </div>
  );
};

ViewJobDetails.js

import React from "react";
import { useLocation,  } from "react-router-dom";
    
export default (props) => {
  const location = useLocation();
        
  console.log(location); // shows jobs on the page yet can't display

  //I also tried 
  //const {state} = location
  //{state.job.description}

  return (
    <>
      <div>
        <div>
          <div>
            <strong>Description:</strong> 
            {location.state.job.description} //doesn't work
            {location.job.description} //doesn't work
            {location.state.description} //doesn't work
          </div>
          <div>
            <strong>Title:</strong> 
          </div>
        </div>
      </div>
    </>
  );
};

console.log output

CodePudding user response:

The passed state jobs is an array. In the component you are accessing a job property that is undefined.

Access the correct state.jobs array and map it to JSX.

Example:

export default (props) => {
  const { state } = useLocation();
  const { jobs } = state || []; // <-- access state.jobs
        
  return (
    <div>
      {jobs.map(job => ( // <-- map jobs array
        <React.Fragment key={job.id}>
          <div>
            <strong>Description:</strong> 
            {job.description}
          </div>
          <div>
            <strong>Title:</strong>
            {job.title}
          </div>
        </React.Fragment>
      ))}
    </div>
  );
};

If on the offhand chance you meant to pass only a single job, i.e. the current job from Jobs, then instead of passing the entire array, pass only the currently iterated job object.

export default () => {
  const navigate = useNavigate();
  const [jobs, setJobs] = useState([]);

  return (
    <div>
      {jobs.map(job => {
        return (
          <div key={job.id}>

            //My attempt using Link
            <Link
              to={`/view-contact-details/${job.id}`}
              state={{ job }} // <-- pass current job
            >
              <button>View</button>
            </Link>

            //My attempt using useNavigate
            <button
              onClick={() => {
                navigate(
                  `/view-contact-details/${job.id}`,
                  { state:{ job } } // <-- pass current job
                );
              }}
            >
              Go To Job details 
            </button>
          </div>
        );
      })}
    </div>
  );
};

Then in the JobDetals component access location.state.job.

export default (props) => {
  const { state }  = useLocation();
  const { job } = state || {};
        
  return (
    <>
      <div>
        <div>
          <div>
            <strong>Description:</strong> 
            {job.description}
          </div>
          <div>
            <strong>Title:</strong>
            {job.title}
          </div>
        </div>
      </div>
    </>
  );
};
  • Related