How can I use React Routes with dynamic params in an onClick event?

Viewed 59

I found the problem is I need to import something named withRouter, but it's incompatible with React Router v6, so I need to convert the entire router with Navigate but I have no idea how to do it from scratch, I will appreciate a lot if someone can guide me a bit, at least with the dynamic Id part of the routing.

I'm making a basic Pokedex project with React, I'm following few steps from this https://www.youtube.com/watch?v=99m9YosJzi4 but looks like some functions that he uses are not currently working. My problem is trying to make an onClick event that gets me to a certain pokemon page using his Id as a parameter. This is the code used in the video:

const Pokedex = props => {
  const {history} = props;
  const classes = useStyles();
  const [pokemonData, setPokemonData] = useState(mockData);

  const getPokemonCard = (pokemonId) => {
    console.log(pokemonData[`/${pokemonId}`]);
    const {id, name } = pokemonData[`${pokemonId}`];
    const sprite = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png`;
    
  return (
    <Grid item xs={4} key={pokemonId}>
      <Card onClick={() => history.push(`${pokemonId}`)} >

BUT, I had problems when the guide started because I wasn't able to use the "props" values in the Routing, so I used { useParams } to make it work well, so my Pokemon.jsx looks like this:

import React from 'react'
import { useParams } from 'react-router-dom'

const Pokemon = () => {
  const {pokemonId} = useParams();
  return (
    <div>this is a pokemon with id {pokemonId}</div>
  );
};

export default Pokemon;

This is my App.jsx:

import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'
import React from 'react';
import Pokedex from './Pokedex';
import Pokemon from './Pokemon';

function App() {
  return (
    //build routing with params
    <Routes>
      <Route path="/" element={<Pokedex />} />
      <Route path="/:pokemonId" element={<Pokemon />} />
    </Routes>
  );
}

export default App

All I need is to make this part of the code work to show something like "this is a pokemon with id {same Id as the link value}" . I already tried to follow steps from documentation but it didn't work and at this point I don't even know what I'm doing wrong, this is literally my first React app.

2 Answers

Issue

The useHistory hook and direct exposure of the history object was deprecated/removed in react-router-dom@6, and there are no route props. The useNavigate hook replaced the useHistory hook, which returns a navigate function instead of a reference to a history object.

useNavigate

Solution

Given routes:

<Routes>
  <Route path="/" element={<Pokedex />} />
  <Route path="/:pokemonId" element={<Pokemon />} />
</Routes>

You are asking how to link/navigate from "/" rendering Pokedex to "/:pokemonId" rendering Pokemon. For this you should use the useNavigate hook to access the navigate function and issue the imperative navigation action. Instead of calling history.push(target) you call navigate(target).

Example:

Pokedex

import { useNavigate } from 'react-router-dom';

const Pokedex =() => {
  const navigate = useNavigate();

  const classes = useStyles();
  const [pokemonData, setPokemonData] = useState(mockData);

  const getPokemonCard = (pokemonId) => {
    const { id, name } = pokemonData[pokemonId];
    const sprite = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png`;

  return (
    <Grid item xs={4} key={pokemonId}>
      <Card onClick={() => navigate(`/${pokemonId}`)}> // <-- issue imperative navigation
        ...
      </Card>
    </Grid>
  );
};

Access the pokemonId route path parameter via the useParams hook.

import { useParams } from 'react-router-dom';

const Pokemon = () => {
  const { pokemonId } = useParams();
  return (
    <div>this is a pokemon with id {pokemonId}</div>
  );
};

can you please also paste your App.js just to check your routes. If path to render Pokemon component is /:pokemonId, you should do () => history.push(`/${pokemonId}`)} on click. / before pokemon id is missing in above code.

Related