Fetching Url type id with useParams (React Router) - reactjs

I'm fetching news articles from The Guardian API. Article id's are like this: "world/live/2020/dec/31/coronavirus-covid-live-news-updates-vaccine-lockdown"
I need to go from article summary to article details and I'm using React Router for this. If I use const { id } = useParams(); and console log it, it gets only gets "world" form the id. How can I get the full id?
<Route path="/:id" component={ArticlePage} />
{topStories.map((story) => (
<Link to={`/${story.id}`}>
<ImageCard key={story.id} story={story} />
</Link>
))}

Issue
Path "/:id" will only match the first path "segment", i.e. "world" from "world/live/2020/dec/31/coronavirus-covid-live-news-updates-vaccine-lockdown".
Solution
If the path is "world/live/2020/dec/31/coronavirus-covid-live-news-updates-vaccine-lockdown" and you are trying to get coronavirus-covid-live-news-updates-vaccine-lockdown as the id then you need to define a route path that matches what you want to extract.
Something like
<Route path="/world/live/:year/:month/:day/:id" component={ArticlePage} />
Now using the params you can extract any of these, including the id.
const { day, id, month, year } = useParams();

Related

React-js undefined props dynamic page when accessing URL directly

I'm trying to create a webshop with React as front-end framework and have gotten stuck on the routing of the products. I currently have all the products in a json table and import these into my webshop which works fine when the product page is accessed through the link but whenever I go to the product page directly I get an error stating that my props are undefined. I have
<Router>
<Switch>
<Route exact path="/products/:productId" component={Product} />
</Switch>
</Router>
as my router to the product page and link to the page using:
<Link to ={{pathname:`/products/` + product.url, ProductdetailProps:{title: product.title, description: product.text, image: product.image}}}>
The Product page looks like this:
export const Product = ({location}) => {
return (
<div>
<img src={location.state.image} alt={backupImage}/>
<p>{location.state.title}</p>
<p>{location.state.description}</p>
</div>
);
};
Should I keep on "creating" the product pages this way and if so can someone help me with this or should make each product page seperately and link those?

Creating react pages with unique urls

I have a route with a url that changes based on the id of the object I clicked to access the route.
//Route
<Route path="InColl/:id" component={InColl}/>
//InColl Component
import React from 'react'
import './css/InColl.css';
export default function InColl({match}) {
const userId = match.params.id;
return (
<div className="margin">
<div className="inv">
Hello World!!!
</div>
</div>
)
}
The :id changes via the link component underneath. I mapped an array of objects each with their own unique id. Depending on which object I click, I will be taken to a new page with the url looking like "
http://localhost:3000/InColl/(The Id of The Object)".
<Link to={"InColl/" + this.props.c._id} >
For some reason the InColl page with the unique id doesn't render anything. I'm not sure what the issue is and I would appreciate some help. Thank you.
/The routes need to be a relative path
change route to
<Route path="/InColl/:id" component={InColl}/>
and link to
<Link to={"/InColl/" + this.props.c._id} >

How to Use Router with 2 different components?

I'am having issues trying to figure it out how to use Router with more then one Wrapper Component.
So my app has a Wrapper component that makes a get call validates the token and has a url parameter. This url is the link to fetch from my api.
I have a users.jsx file that lists the users and a userdetails.jsx file that lists the details of each user. The key is the CN.
My users.jsx already has a dynamic link that uses the username(cn) for each user in the list.
Now my app renders the user list in my users.js file using the Wapper component and passing the url to fetch for the user list.
What i need is to have the userDetails integrated here.
users.js
const IndexPage = () => (
<Layout>
<MainComponentWrapper url="http://localhost:5000/user">
<User />
</MainComponentWrapper>
</Layout>
)
My other url is: http://localhost:5000/user/<cn>to fetch for the details.
I was trying to come with a code like this, but it doesn' work:
const IndexPage = () => (
<Layout>
<Router>
<div>
<MainComponentWrapper url="http://localhost:5000/user">
<User path="/users" />
</MainComponentWrapper>
</div>
<div>
<MainComponentWrapper url="http://localhost:5000/user/<cn>">
<UserDetails path="/users/:cn" />
</MainComponentWrapper>
</div>
</Router>
</Layout>
)
I want to navigate to the user details if i click on a user in the list
Also i am using gatsby plugin :
{
resolve: `gatsby-plugin-create-client-paths`,
options: { prefixes: [`/user/*`] },
},
```
refer this react-router-exact , read the first answer , then read the second answer , you need to undestand the concept of exact (its described in answer 1) in react router then you have to combine it with the switch (in the answer two) statement .

React router accessing route properties in route component

I am using React router v4 to render routes. I have a simple route component which routes to a list of items and an edit existing/add new item. This is a simple tab component built with bootstrap. I'd like to change the title of the tab component to either Add new or Edit existing depending on whether the route has an id property.
Ideally I'd like to avoid needing to create additional components as it doesn't feel like this will enhance readability of the code.
public render() {
const { match, location } = this.props;
const customers = cx({ active: !location.pathname.includes("AddEdit") });
const editItem = cx({ active: location.pathname.includes("AddEdit") });
const hasIdParam = {/* Some way to read match params to get the id */};
return <div className='nav-component-container'>
<nav>
<ul>
<li role="presentation" className={items}><NavLink to={`${match.url}/All`} activeClassName='active'>Items</NavLink></li>
<li role="presentation" className={editItem}>
<NavLink to={`${match.url}/AddEdit`} activeClassName='active'>
{/* I'd like this to say either new item or edit existing based on whether the current route has an id parameter or not */}
</NavLink>
</li>
</ul>
</nav>
<Switch>
<Route path={`${match.url}/All`} component={Customers} {...this.props}></Route>
<Route path={`${match.url}/AddEdit/:id?`} component={Item}></Route>
</Switch>
</div>;
}
There are various hacks - the best of which seems to be reading the location.pathname property and use it to determine whether it's an edit or add new - that will suffice but I can't help feeling that I'm missing something in
In your Item component,you will get url parameter i.e. id through match object of Route path .
var strId = props.match.params.id //ecma5
let strId = this.props.match.params.id //ecma6
based on strId you can changes the tab label.
if(strId){
//use edit lable
}else{
//add label
}
You can try separating routes for edit and add but can use the same component with a type prop.
Example
<Switch>
<Route path={`${match.url}/All`} component={Customers} {...this.props}></Route>
<Route path={`${match.url}/Details/:id?`} component={()=>(<Item type="detail" />)}></Route>
<Route path={`${match.url}/Edit/:id?`} component={()=>(<Item type="edit" />)}></Route>
<Route path={`${match.url}/Add/:id?`} component={()=>(<Item type="add" />)}></Route>
</Switch>
Then on your Item component you can check the this.props.type and render it accordingly.

react router redux url

I am making my first web-app using react, react router v4, and redux/react-router-redux.
it is a shopping site. I have my list of my products saved in the store and can access them fine. I have produced a products list page, when clicking on the products' image i have routing setup to take me to a new url(/'productmodel').
Currently I have a 'ProductPage' component for which I have passed in props relevant to the specific product, for each corresponding route, within my router. This seems like a very long way of doing things.
What I would like to do is render for each of the routes and then have the ProductPage component itself, render the right product depending on the route (URL address).
What is the best way to do this??
Thank you in advance :)
Are you after something like this?
ProductsListPage:
....
render() {
<div>
{this.props.products.map(product =>
<Link key={product.id} to={"/product/"+product.id}>
{product.name}
</Link>
)}
</div>
}
....
ProductPage:
....
componentWillMount() {
this.props.actions.getProduct(this.props.match.params.productid);
}
....
render() {
<div>
<span>{this.props.product.name}</Link>
</div>
}
....
Your route for product page would look like this:
<Route exact path="product/:productid" component={ProductPage} />
So what's happening here is when you click on a product on Products List page, you get redirected to the product page that has the product id as a parameter. On component mount on product page, you retrieve the product passing the productid from params (url).
ok so I manage to do it!
I created a ProductPageContainer inorder to pass my products list from the store:
function mapStateToProps(state) {
let products = state.kitsProducts;
return {
products: products
};
};
I then, within my component, got the productid from the params; as suggested by Hossein:
createProductPageComponent() {
let activeProduct = this.props.products.filter(product => product.id === this.props.match.params.productid)
return activeProduct.map(product =>{
return (
<ProductPage
key={product.id}
brand={product.brand}
productName={product.model.toUpperCase()}
price={"£"+product.price}
productImage={product.image}
text={product.text}
/>
)
})
}
and now my product page renders to the the right route, depending on which product was selected in the previous product list page. And the right product, depending on what route it has been rendered in.
Thanks Hossein!!! You helped me more than you may think!

Resources