I'm making a movie app in React.
For fetching data I'm using a custom hook named useFetch
I'm fetching a list of genres in Genre
. Based on the genre id I'm creating a new route to render a list of movies in MoviesFromGenre
. Using the movie's id, when I click on a Movie
component I'm making a new route to a MovieDetails
component.
In MovieDetails
I want to add a Credits
component. For that, I'm passing the movie id as props, then based on that id I'm fetching a list of the movie credits, but when I'm mapping the array I get this error:
Cannot read properties of undefined (reading 'map')
Sandbox link
useFetch
import { useReducer, useEffect } from "react";
import axios from "axios";
const ACTIONS = {
FETCH_DATA: "fetch-data",
ERROR: "error"
};
const initialState = {
data: [],
loading: false,
error: null
};
function reducer(state, { type, payload }) {
switch (type) {
case ACTIONS.FETCH_DATA:
return { data: payload, loading: false };
case ACTIONS.ERROR:
return { data: [], error: payload };
default:
return state;
}
}
function useFetch(url, data) { // Passing a data argument is necessary: https://stackoverflow.com/questions/71668249/cant-map-fetched-data-from-custom-usefetch-hook
const [state, dispatch] = useReducer(reducer, {...initialState, data});
useEffect(() => {
axios
.get(url)
.then((res) => {
dispatch({ type: ACTIONS.FETCH_DATA, payload: res.data });
})
.catch((e) => {
dispatch({ type: ACTIONS.ERROR, payload: e.error });
});
}, [url]);
return state;
}
export default useFetch;
MovieDetails
import React, { useState } from "react";
import { useParams } from "react-router-dom";
import Credits from "../Credits/Credits";
import useFetch from "../Utils/useFetch";
import "../Utils/useFetch";
import { API_KEY, API_URL } from "../../api/requests";
function MovieDetails() {
const { movieId } = useParams();
const BASE_URL = `${API_URL}/movie/${movieId}?api_key=${API_KEY}`;
const { data: movie, loading, error } = useFetch(BASE_URL, { movie: [] });
console.log(movie);
return (
<div className="movie-details">
{movie.title}
<Credits movieId={movie.id} />
</div>
);
}
export default MovieDetails;
Credits
import React from "react";
import useFetch from "../Utils/useFetch";
import { API_KEY, API_URL } from "../../api/requests";
function Credits(props) {
const { movieId } = props;
const BASE_URL = `${API_URL}/movie/${movieId}/credits?api_key=${API_KEY}`;
const { data: credits, loading, error } = useFetch(BASE_URL, { credits: [] });
console.log(movieId);
return (
<div className="credits">
{credits.id}
{loading
? "Loading"
: credits.credits.cast.map((castMember) => <h1>{castMember}</h1>)}
{error ? error : null}
</div>
);
}
export default Credits;
CodePudding user response:
The issue you have here seems to be that you are trying to access an object credits
inside credits
where you can already access cast
.
{loading ? (
"Loading"
) : credits && credits.cast ? (
credits.cast.map((castMember) => <h1>{castMember.id}</h1>)
) : (
<div>{"Error fetching credits"}</div>
)}
works for me.
I've added an extra check for credits
and credits.cast
just to avoid trying to access that object when undefined. I've also changed <h1>{castMember}</h1>
to <h1>{castMember.id}</h1>
because I then got an error that the object wasn't a valid react child, so just printing out the id here to show that you can now access the properties of castMember
.
Here's the updated sandbox: https://codesandbox.io/s/tmdb-credits-forked-xwqp1b?file=/src/Components/Credits/Credits.js:428-630