I am working with Context API when I create context object and call in Film my Films are loading but when also working well but when I call this fav context object with my Films component it just load Film data and when we click the film it does not display the record.Route is in my main file outlet is in parent component. Film.js File
import { useParams } from 'react-router-dom';
import React from 'react'
import {useFav} from '../../context/FavContext'
export const Film = ({list}) => {
const { id } = useParams();
const film = list.find((item, index) => parseInt(id) === index + 1);
const [fav,updateFav] = useFav();
function clicked(ev){
updateFav(
'films',parseInt(id),film)
}
let details = (
<>
<p>{film && film.title}</p>
<p>{film && film.release_date}</p>
</>
);
return (
<div>
<h2>Film Details</h2>
{details}
{fav.id !== 0 && <p>The current id of the favourite is {fav.id}</p>}
{fav.data.title && <p>Favourite film is {fav.data.title}</p>}
<p>
<button onClick={clicked}>
{fav.id === parseInt(id) ? (
<span>
<i className="material-icons">favorite</i> Clear Fav
</span>
) : (
<span>
<i className="material-icons">favorite_border</i> Set as Fav
</span>
)}
</button>
</p>
</div>
);
}
--Films.js
import React from 'react'
import './films.css'
import { NavLink, Outlet } from 'react-router-dom';
import {useFav} from '../../context/FavContext'
export const Films = (props) => {
const { list } = props;
const [fav]= useFav();
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 ? 'activeLinkF':'none')}>
{film.title}{' '}
{fav.type === 'films' && index + 1 === parseInt(fav.id) && (
<>
<span className="material-icons">favorite</span> FAVOURITE!
</>
)}
</NavLink>
</p>
))}
</div>
<Outlet/>
</>
)
}
--ContextAPI
import React from 'react';
import {createContext,useContext,useState} from 'react'
const FavContext = createContext();
//Now we have a context object
function FavProvider(props){
//create the provider and its functionality
//create a state variable to hold the information,whenever we want to hold the
//information we use state variable up to the top.
const shape = {
type:'', //films, planets,people
id:0, //id of film ,planet and object
date:{} //the actual data object
}
const [fav,setFav] = useState(shape);
function updateFav(type,id,data){
setFav({
type,
id,
data,
})
}
return <FavContext.Provider value={[fav,updateFav]} {...props}/>
}
function useFav(){
//For pages that want to access the context object's value
//useContext is the hook to use the object creating by create Context hook.
const context = useContext(FavContext)
if(!context) throw new Error('Not inside the provider')
return context; //inside this object fav,setFav
}
export{useFav, FavProvider};
--App.js
import './App.css';
import Header from '../Header/Header';
import SearchBar from '../SearchBar/SearchBar';
import { useEffect } from 'react';
// import SearchResults from '../SearchResults/SearchResults';
import { Main } from '../Main/Main';
import { useState } from 'react';
import { useLocation } from 'react-router-dom';
import {FavProvider} from '../../context/FavContext'
export default function App(props) {
const name = 'Company Name';
const { pathname } = useLocation();
const [page, setPage] = useState(pathname);
const [keyword, setKeyword] = useState('');
function saveSearch(term) {
setKeyword(term);
}
useEffect(() => {
//see if /planets => /films change keyword
//if /planets => /planets/5 do NOT change keyword
let newPath = pathname.split('/')[1];
let oldPath = page.split('/')[1];
if (newPath !== oldPath) {
setPage(pathname);
console.log('CHANGED the base path');
setKeyword('');
} else {
console.log('SAME base path');
}
}, [pathname,page]);
return (
<FavProvider>
<div className="App">
<Header company={name} />
<SearchBar keyword={keyword} saveSearch={saveSearch} />
<main className="content">
<Main keyword={keyword} />
</main>
</div>
</FavProvider>
);
}
--Main Routes and Fetch data with useEffect
import {Routes,Route, useLocation} from 'react-router-dom'
//import {Redirect} from 'react'
import { People } from '../People/People'
//import { Planet } from '../Planet/Planet'
import {useState,useEffect} from 'react'
import { Person } from '../Person/Person'
import { Home } from '../Home/Home'
import { Sub } from '../Sub/Sub'
import { Films } from '../Films/Films'
import { Film } from '../Film/Film'
import { Planets } from '../Planets/Planets'
import { Planet } from '../Planet/Planet'
export const Main = (props) => {
const { pathname } = useLocation();
const { keyword } = props;
const [people, setPeople] = useState([]);
const [films, setFilms] = useState([]); //list of films
const [planets, setPlanets] = useState([]); //list of planets
let name = ['Kylo','Ray','Luke'];
useEffect(() => {
(async function () {
let url = 'https://swapi.dev/api';
if (pathname.indexOf('/people') > -1) {
let resp = await fetch(`${url}/people?search=${keyword}`);
let data = await resp.json();
setPeople(data.results);
}
if (pathname.indexOf('/films') > -1) {
let resp = await fetch(`${url}/films?search=${keyword}`);
let data = await resp.json();
setFilms(data.results);
}
if (pathname.indexOf('/planets') > -1) {
let resp = await fetch(`${url}/planets?search=${keyword}`);
let data = await resp.json();
setPlanets(data.results);
}
})();
}, [pathname, keyword]); //run this each time the route changes
return (
<div className='mainContent content'>
<Routes>
<Route path="/people" element={<People list={people} />}>
<Route path="/people/:id" element={<Person list={people} />}/>
{/* Person is passed prop with fetch results */}
</Route>
<Route path="/films" element={<Films list={films} />}>
<Route path="/films/:id" element={<Film list={films} />}/>
{/* Person is passed prop with fetch results */}
</Route>
<Route path="/planets" element={<Planets list={planets} />}>
<Route path="/planets/:id" element={<Planet list={planets} />}/>
{/* Person is passed prop with fetch results */}
</Route>
<Route path="*" element={<Home name = {name}active={false}time={new Date()-50000000}>
{/**Its children */}
<Sub/>
</Home>}
/>
</Routes>
</div>
)
}[![enter image description here][1]][1]
When I click the Film Name I got the error in the console as in sending image. How can I fix it?