简体   繁体   中英

React router dom dynamic routing

I am doing a React.js project. I am retrieving dat from the Star Wars API rendering a list of films on the screen and now I am trying to route every film to its own page through react-router-dom. Unfortunately, I am not able to make it work. it crash when I try to routing dynamically.

UPDATE AFTER ANSWER OF REZA

This is the App.js:

import './App.css';    
import { Route, Routes } from "react-router-dom";    
import Home from './components/Home';
import ItemContainer from './components/ItemContainer';
import Navbar from './components/Navbar';

function App() {
  return (
      <>
      <Navbar />
        <Routes>
            <Route exact path='/' element={<Home />} />
            <Route exact path="/:movieId" element={<ItemContainer />} />
        </Routes> 
        </> 
  );
}    
export default App;

This is the ItemContainer:

import { useEffect, useState } from "react";    
import MovieDetail from "../MovieDetail";
import { useParams } from "react-router-dom";    
const ShowMovie = (movieId) => {
    const [result, setResult] = useState([]);

    const fetchData = async () => {
        const res = await fetch("https://www.swapi.tech/api/films/");
        const json = await res.json();
        setResult(json.result);
    }
    useEffect(() => {
        fetchData();
    }, []);
    return new Promise((res) => 
    res(result.find((value) => value.properties.title === movieId)))
}

const ItemContainer = () => {
    const [films, setFilms] = useState([]);
    const { movieId } = useParams([]);
    console.log('params movieId container', movieId)

    useEffect(() => {
        ShowMovie(movieId).then((value) => {
            setFilms(value.properties.title)
        })
    }, [movieId])
    return (
            <MovieDetail key={films.properties.title} films={films} />
    );
}     
export default ItemContainer;

The console.log doesn't give anything. Also, this is the whole code in sandbox .

Modify App.js like this:

function App() {
  return (
    <>
      <Navbar />
      <Routes>
        <Route exact path="/" element={<Home />} />
        <Route exact path="/:movieId" element={<ItemContainer />} />
      </Routes>
    </>
  );
}

ShowMovie is declared like a React component, but used like a utility function. You shouldn't directly invoke React function components. React functions are also to be synchronous, pure functions. ShowMovie is returning a Promise with makes it an asynchronous function.

Convert ShowMovie into a utility function, which will basically call fetch and process the JSON response.

import { useEffect, useState } from "react";    
import MovieDetail from "../MovieDetail";
import { useParams } from "react-router-dom";

const showMovie = async (movieId) => {
  const res = await fetch("https://www.swapi.tech/api/films/");
  const json = await res.json();
  const movie = json.result.find((value) => value.properties.title === movieId));

  if (!movie) {
    throw new Error("No match found.");
  }

  return movie;
}

const ItemContainer = () => {
  const [films, setFilms] = useState({});
  const { movieId } = useParams();

  useEffect(() => {
    console.log('params movieId container', movieId);

    showMovie(movieId)
      .then((movie) => {
        setFilms(movie.properties.title);
      })
      .catch(error => {
        // handle error/log it/show message/ignore/etc...

        setFilms({}); // maintain state invariant of object
      });
  }, [movieId]);

  return (
    <MovieDetail key={films.properties?.title} films={films} />
  );
};

export default ItemContainer;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM