简体   繁体   中英

React router is not rendering single id routes on refresh

I'm working on a personal project and i have now been stuck with a react router problem since a couple of day.

I'am fetching an API and trying to render a route with a single id so when i click on the card link everything is working fine but as soon as a try to render the link manually on a new tab for example i got a console error

TypeError: Cannot read property 'position_name' of undefined

 | const Articles = ({ location }) => (
  5 |   <ArticleComponent
> 6 |     position_name={location.state.position_name}
  7 |     workplace_name={location.state.workplace_name}

Here are my routes on the APP.js file

    <Switch>
      <Route exact path="/" component={JobCard} />
      <Route path="/jobs/:_id" component={Articles} />
    </Switch>

and the component where i fetch the card.

  <div key={job._id} className="blog-card">
                    <div className="description">
                      <Link
                        className="link-apply"
                        to={{
                          pathname: `/jobs/${job._id}`,
                          state: job
                        }}
                      >
                        <h5 className="position-name">{job.position_name}</h5>
                        <p className="place">{job.workplace_name}</p>
                        <p className="location-job">{job.location}</p>
                      </Link>
                    </div>

So what i'm trying to achieve is to be able to render the articles when i type the link manually, for example: http://localhost:3000/jobs/5ccc770c6ac54350001f0954

But it's only rendering when i click on the card for some reasons.

Thanks in advance for the help

But it's only rendering when i click on the card for some reasons.

When you click on the <Link> in your card, you can see your request looks like following :

<Link
  className="link-apply"
  to={{
    pathname: `/jobs/${job._id}`,
    state: job
  }}
>

When doing this, your request contain 2 information :

  1. It wants to go to the path pathname
  2. It sends along a state, containing your job values

So in your component

const Articles = ({ location }) => (
  <ArticleComponent
    position_name={location.state.position_name}
    workplace_name={location.state.workplace_name}
    . . .
  />
);

location object looks like this :

location = {
  pathname: ‘your_url’,
  state: {
    position_name: ‘your_string’,
    workplace_name: ‘your_string’
    . . .
  }
}

And that's why calling location.state.position_name works. However, when you type your URL manually, location will only look like this :

location = {
  pathname: ‘your_url’
}

Because, you actually didn't passed any state ! It is impossible to achieve this, you cannot add anything to your location props by typing your URL. So, let's do the work.

Solution

You need another way to get your state information. As you can retrieve anything from your database, the following should do. Just change your <Article> component :

Article.js

// You can pass the whole props or destructure the ones you need
// like you did before. In my example, I don’t nee anything so I
// just leave it blank
const Articles = () => {
  // Not the best method but it works everywhere, since I don’t know
  // your whole project structure. Read below for more information.
  const pathname = window.location.pathname.split(‘/‘);
  const job_id = pathname[pathname.length - 1];

  // Make your query here
  // Assume query() is a function that return a job with given id
  // from your database
  const job = query(job_id);
  let position_name;
  let workplace_name;

  // If query was successful
  if (job) {
    position_name = job.position_name;
    workplace_name = job.workplace_name;
  }

  return (
    <ArticleComponent
      position_name={position_name}
      workplace_name={workplace_name}
      . . .
    />
  );
};

Thus, you retrieve needed information without anything more than your job_id, and you allow users to query from a direct URL.

Note about pathname

I retrieved job_id from window.location , which is a default javascript URL parser. However, it's kinda ugly, not to mention it isn't quite scalable.

According to how your project tree is structured, if your element is attached to a router, you can use query_string library, as mentioned in this topic (be aware of some methods that doesn't work anymore in recent React version).

Since your user is potential to errors (like, for example, entering an id that doesn't exist), you need to deal with errors in your query, for example by returning null values, or redirect to a 404 if query didn't succeed.

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