ReturnMack
ReturnMack

Reputation: 25

Clicking on a Card component should create a new route and display further information

I'm new to react-router v6

I have 4 components, App, CardList, Card and CardInfo. There is data (an array of objects, each object represents a movie) coming from an API that gets saved in App.js with useState hook.

Within CardList, I use map to iterate over the array to generate a bunch of Card components and passing in data via props.

What I want now is to be able to click on any Card component and for it to navigate to a different route, e.g. localhost:3000/1 (for Card with the id of 1), localhost:3000/2 (for Card with the id of 2) etc. and within each route that corresponds to the Card id, there would be a box/modal (CardInfo.js) component with further information about the movie.

I'm trying to accomplish this with react-router-dom (version 6).

It looks like within the CardList.js or Card.js component you would need to create links (<Link>) and routes (<Route>) (both which are equal to the number of movies in the data) on the fly with the .map function and wrapping the Card component in <Link> and <Route> tags. Something like


{items.map(movie => (
               <Route path="/:id" element={<Card items={movies} />} exact>
               <Link to={`/${movie.id}`}>
                <Card   
                    key={movie.id}
                    id={movie.id}
                    name={movie.name}
                    description={movie.description}   
                    img={movie.image_url}
                 />
               </Link>
               </Route>
        ))}

Obviously that doesn't work.

App.js:

    import './App.css';
    import CardList from './features/Card/CardList';
    import CardInfo from './features/Card/CardInfo';
    import { useState, useEffect } from "react";
    import { BrowserRouter, Route, Routes } from 'react-router-dom';

    function App() {
       const [movies, setMovies] = useState([]);
     
       useEffect(() => {
         const getData = fetch('https://api.com/movies')
         .then(data => data.json())
         .then(items => { setMovies(items) })
       }, [])


      return (
        <BrowserRouter>
          <Routes>
            <Route path="/:id" element={<CardInfo items={movies} />} exact></Route>
          </Routes>
            <CardList items={movies} />
        </BrowserRouter>
      );
    }

    export default App;

CardList.js:


import React from 'react'
import Card from './Card'
import "./CardList.css";

const CardList = ({ items }) => {
  return (
    <div className="cardList">
        {items.map(movie => (
                <Card   
                    key={movie.id}
                    id={movie.id}
                    name={movie.name}
                    description={movie.description}   
                    img={movie.image_url}
                 />
        ))}
    </div>
  )
}

export default CardList

Card.js:


import React from 'react'
import "./Card.css";
import { Link } from 'react-router-dom';

function Card(props) {

  return (
    <Link to={`/${props.id}`}> 
     <div className="card">
        <div>
            <img src={props.img} />
            <h2>{props.name}</h2>
        </div>
     </div>
    </Link>
  )
}

export default Card

CardInfo.js:


import React from 'react'

function CardInfo(props) {
  return (
    <div>
      <p>{props.description}</p>
    </div>
  )
}

export default CardInfo

Upvotes: 2

Views: 1293

Answers (1)

aletax30
aletax30

Reputation: 36

your code structure is correct. You just need to useLink, you don't need en external Route component for every card you map. Here is a link for further information. Hope you find it helpful. https://stackoverflow.com/a/57059249/17715977

Upvotes: 2

Related Questions