Reputation: 693
I cannot figure out how to link to a specific product in my simple e-commerce site in React. The documentation makes it seem simple enough but it's all for classes rather than functional components like I am using so maybe that is where my problem is.
App.js
import { BrowserRouter as Router, Link, Route, Switch } from "react-router-dom";
<Router>
<div className="App">
<Header />
<Switch>
<Route path="/" component={Main} />
<Route path="/:book" component={Single} />
</Switch>
</div>
</Router>
Main.js
const Main = () => {
return (
<div id="main">
{data.map((book, i) => {
return (
<div key={i} className="squares">
<img
src={images[book.picture]}
className="covers"
alt="book cover"
/>
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
<h3>
**<Link to="/:book">{book.title}</Link>**
</h3>
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
<p>
Author: <em>{book.author}</em>
</p>
<p>
Price: <strong>{book.price}$</strong>
</p>
<p>{book.inventory} left in stock</p>
</div>
Single.js
const Single = (props) => {
let { book } = useParams();
console.log(book); //prints :book
I know it's typically this.props.match.params.book so I figured I would just need to leave off the 'this' but obviously I am missing something. I have tried it before my function, in my function, anything I could think of. Are objects not allowed to be passed in the url?
Upvotes: 1
Views: 2914
Reputation: 693
The problem ended up coming from here -
<Link to="/:book">{book.title}</Link>
This is the exact format that the React Docs gave and everyone who attempted to help me copied this error which is why none of the given answers worked for me. This link sent me to localhost:3000/:book because that is the literal string.
The answer I needed was
<Link to={`/${i}`}>>{book.title}</Link>
You'll note that I am passing the id instead of the object itself. It is also possible to pass the object but in my case the best way was to to pass the id which I then used to retrieve the book.
Either way, the part that I was missing were the special characters surrounding the string which let the app know that the url was a dynamic value.
Upvotes: 2
Reputation: 6582
You can simply use useParams
hook from react-router-dom
like this:
let { book } = useParams();
or you can use params
without destructuring like this:
let params = useParams();
let book = params.book
You can also send data as state
to your url like this:
<Link
to={{
pathname: "/home",
state: { fromDashboard: true }
}}
/>
EDIT:
in order to achieve what you have in mind you need to change this line in your Main.js
file:
<Link to="/:book">{book.title}</Link>
to this:
<Link to={{pathname:'/book',state:{book:book}}}">{book.title}</Link>
and change your route accordingly:
<Switch>
<Route path="/" component={Main} />
<Route path="/book" component={Single} />
</Switch>
Now in your Single.js
File you can get book object
like this:
first add import 'useLocation' from 'react-router-dom';
then
const location = useLocation();
const book = location.state.book; // You have book object here
Upvotes: 1
Reputation: 1001
<Route path="/:book" component={Single} />
here book can be primitive data type like string
,number
,bool
etc. you cannot send object as url parameter.
Change the route and send book as
<Link to={{pathname:'/newRoute',state:{book:book}}}">{book.title}</Link>
Upvotes: 0