dbrewster
dbrewster

Reputation: 693

How to pass and retrieve data over the url in React

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

Answers (3)

dbrewster
dbrewster

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

Taghi Khavari
Taghi Khavari

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

Prakash Reddy Potlapadu
Prakash Reddy Potlapadu

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

Related Questions