render in react router dom v6

Viewed 1306

I am following an example of how you render a function and pass properties, to get some data from the dom.

--- App.jsx ---

import { Routes, Route } from "react-router-dom";

// Components
import Listado from "./components/Listado";
import Detalle from "./components/Detalle";

function App() {

  const addOrRemoveFromFavs = e => {
    const btn = e.currentTarget;  // console.log(btn);
    const parent = btn.parentElement; // console.log(parent)
    const imgURL = parent.querySelector('img').getAttribute('src'); 
    const title = parent.querySelector('h5').innerText;
    const overview = parent.querySelector('p').innerText;
    
const movieData = {
      imgURL, title, overview
    }
    console.log(movieData);
  }

  return (
    <>
      <Header />
      <div className="container mt-3">
        <Routes>
          <Route path="/" element={<Login />} />
          <Route path="/listado" render={ (props) => <Lisstado addOrRemoveFromFavs={addOrRemoveFromFavs} {...props}/>} />
          <Route path="/detalle" element={<Detalle />} />
          </Routes>
      </div>
      <Footer />
    </>
  );

}

According to the documentation in react v6, the render or component is no longer used, so I don't know how to pass the information, here I show another fraction of code where I want to share the function and from here obtain data from the DOM. When making a console of the props following the example, you should get an object with information but it is not like that, besides it stops loading the information and is now blank.

-- listado.jsx ---

import { useEffect, useState } from "react";

import { Link, Navigate } from "react-router-dom";
import axios from "axios";
import swAlert from "@sweetalert/with-react";


const Listado = (props) => {
  
  let token = sessionStorage.getItem('token');

  console.log(props);

  onst [ moviesList, setMoviesList ] = useState([]);

  useEffect(() => {
    const endpoint = 'https://api.themoviedb.org/3/discover/movie?api_key=8764e6417ae516fb86bc820ee865a6d8&language=es-US&page=1'
    axios.get(endpoint)
      .then(response => {
        const apiData = response.data;
        setMoviesList(apiData.results);
      })
      .catch(error => {
        swAlert(<h2>Hubo errores, intenta más tarde</h2>)
      })
  }, [setMoviesList]);  

  
  return (
    <>
    { !token && <Navigate to="/" /> }
    <div className="row">
    {
        moviesList.map((oneMovie, index) => {
          return (
            <div className="col-3" key={index}>
              <div className="card my-4">
                <img src={ `https://image.tmdb.org/t/p/w500/${oneMovie.poster_path}` } className="card-img-top" alt="..." />
                <button className="favourite-btn">
                  
                </button>
                <div className="card-body">
                  <h5 className="card-title">{ oneMovie.title.substring(0, 20) }...</h5>
                  <p className="card-text">{ oneMovie.overview.substring(0, 100) }...</p>
                  <Link to={`/detalle?peliculitaID=${oneMovie.id}`} className="btn btn-primary">View Details</Link>
                </div>
              </div>
            </div>
          )
          })
        }
        </div>
    </>
  )
}

export default Listado

I appreciate any suggestion

1 Answers

If you are just trying to render the Lisstado component on the "/listado" path and pass a addOrRemoveFromFavs prop, you do this just like any other time you are passing props to a component. Keep in mind the the Route components take a ReactNode, a.k.a. JSX, on the element prop, so passing props is just the same is it is anywhere else in React.

Example:

<Routes>
  <Route path="/" element={<Login />} />
  <Route
    path="/listado"
    element={<Lisstado addOrRemoveFromFavs={addOrRemoveFromFavs} />}
  />
  <Route path="/detalle" element={<Detalle />} />
</Routes>

Additionally, you shouldn't be querying the DOM for the values in the passed callback, pass them to the callback directly in the child component.

Example:

App

const addOrRemoveFromFavs = movieData => e => {
  console.log(movieData);
}

Listado

const Listado = ({ addOrRemoveFromFavs }) => {
  const token = sessionStorage.getItem('token');

  const [ moviesList, setMoviesList ] = useState([]);

  useEffect(() => {
    ...
  }, [setMoviesList]);

  if (!token) {
    return <Navigate to="/" />;
  }
  
  return (
    <div className="row">
      {moviesList.map((oneMovie, index) => {
        // create movieData object
        const movieData = {
          imgURL: `https://image.tmdb.org/t/p/w500/${oneMovie.poster_path}`,
          overview: oneMovie.overview,
          title: oneMovie.title
        };

        return (
          <div className="col-3" key={index}>
            <div className="card my-4">
              <img
                src={ `https://image.tmdb.org/t/p/w500/${oneMovie.poster_path}`}
                className="card-img-top"
                alt="..."
              />
              <button
                className="favourite-btn"
                onClick={addOrRemoveFromFavs(movieData)} // <-- pass to callback
              >
                
              </button>
              <div className="card-body">
                <h5 className="card-title">
                  {oneMovie.title.substring(0, 20) }...
                </h5>
                <p className="card-text">
                  {oneMovie.overview.substring(0, 100) }...
                </p>
                <Link
                  to={`/detalle?peliculitaID=${oneMovie.id}`} 
                  className="btn btn-primary"
                >
                  View Details
                </Link>
              </div>
            </div>
          </div>
        )}
      )}
    </div>
  )
};
Related