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 :
pathname
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.