I am working on react-router-dom@6.8
and fetching data using useEffect
hook and updated data with useState
hook.
My routes are in Main
component and nested route of "/films"
which have film details is in Films
component. I have attached the screenshot in which I am just able to access the specific id of films but not displaying film detail. Film
is accessed via props in Films
using method findFilms
.
Main.js
import { Routes, Route } from 'react-router-dom'
import { Films } from '../Films/Films'
import { Home } from '../Home/Home'
export const Main = (props) => {
return (
<div className='mainContent'>
<Routes>
<Route path="/films/*" element={<Films />}></Route>
<Route path="/planets/*" element={<Planets />}></Route>
<Route path="/people" element={<People list={people} />}>
<Route path=":id" element={<Person list={people} />}></Route>
{/* Person is passed prop with fetch results */}
</Route>
<Route path="*" element={<Home />}></Route>
</Routes>
</div>
)
}
Films.js
import React from 'react'
import { NavLink, Route, Routes } from 'react-router-dom';
import { Film } from '../Film/Film'
import './films.css'
export const Films = (props) => {
const [list, setList] = useState([]);
useEffect(() => {
(function getFilms() {
let url = 'https://swapi.dev/api/films/';
fetch(url)
.then((resp) => {
if (!resp.ok) throw new Error(resp.statusText);
return resp.json();
})
.then((data) => {
setList(data.results);
})
.catch(console.warn);
})();
}, []);
function findFilm(id) {
return list.find((item, index) => parseInt(id) === index + 1);
}
return (
<>
<div className="results">
<h2>Film List</h2>
{list.length === 0 && <p>No films...</p>}
{list.map((film, index) => (
<p key={film.title}>
<NavLink to={`/films/${index + 1}`} className={({isActive}) => (isActive ? "activeLink" : 'none')}>
{film.title}
</NavLink>
</p>
))}
</div>
<div className="details">
<Routes>
<Route path="/films/:id" element={<Film findFilm={findFilm} />} />
</Routes>
</div>
</>
)
}
Film.js
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import React from 'react'
export const Film = ({ findFilm }) => {
const [film, setFilm] = useState(null);
const { id } = useParams();
useEffect(() => {
setFilm(findFilm(id));
}, [findFilm, id]);
let details = (
<>
<p>{film && film.title}</p>
<p>{film && film.release_date}</p>
</>
);
return (
<>
<h2>Film Details</h2>
{film && details}
</>
)
}
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/App/App';
import { BrowserRouter } from 'react-router-dom'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
Main
component is being rendered in App
component. Please look in the code either I will have to make css file className results to display data or it's a routing problem why code is not able to display data in the page planet is sub component of Planet.
Nested Routes
components build their routes relative to the parent Route
component. If the Films
component is rendered on path="/films/*"
then all descendent routes will be relative from "/films"
. A descendent route path="/films/:id"
resolves to "/films/films/:id"
which probably not what you intended.
Remove the leading "/films"
segment of the descendent routes.
<Routes>
<Route path="/:id" element={<Film findFilm={findFilm} />} />
</Routes>