I've fetched movies from an API and stored the movie object in a state value called 'movies'. I then pass this state as a prop to my slideshow component where I want to access the poster_path property of this object to display.
When I receive the object, I destructure it and take the 'poster_path' and store it as a variable called 'posters' eg: let posters = movies.poster_path.
When I console log 'movies' it gives me all of the movies, but when I log this variable it is giving me 'undefined'. I'm sure I'm missing something small but I can't figure it out. (I don't show the full route that my state travels but it starts in App.js and it's received in the Slideshow component).
Basically, how do I get this value so I can then use it within my slideshow?
Apologies in advance for my code as I'm still pretty new to React.
import React, { useState, useEffect } from 'react';
// import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
//Components
import Header from './components/Header'
import MusicPlayer from './components/MusicPlayer';
//Pages
import Home from './pages/Home';
import Kids from './pages/Kids';
import Movies from './pages/Movies';
import Music from './pages/Music'
//CSS
import './css/Header.css'
import './App.css';
import './css/Movies-Kids.css'
import './css/Music.css'
import './css/Home.css'
import './css/HeroSlider.css'
import './css/FilterButton.css'
import './css/MusicPlayer.css'
import { Delete } from '@mui/icons-material';
function App() {
// * MOVIE API *
//State
const [movies, setMovies] = useState([])
//API URL
const url = 'https://api.themoviedb.org/3/discover/movie?api_key=APIKEY&with_genres=28/';
//Async function to fetch API
async function getMoviesData (url) {
await fetch(url).then(res => res.json()).then(data => setMovies(data.results))
}
//Use Effect
useEffect(() => {
getMoviesData(url);
}, [])
return (
<div className='app'>
<div className="header">
<Header Home={Home} Movies={Movies} Kids={Kids} Music={Music} movies={movies} />
</div>
<div className="music-player">
{/* <MusicPlayer /> */}
</div>
</div>
)
}
export default App
import React, { useState, useEffect } from 'react'
//Images Posters
import BackDrop from '../images/sandwich.jpg'
import FoodBanner from '../images/foodbanner.jpg'
import Batman from '../images/batman.jpg'
import Pulpfiction from '../images/pulp-fiction.jpg'
// const posters = [Pulpfiction, Batman, BackDrop, FoodBanner, FoodBanner];
const delay = 50000;
function Slideshow({movies}) {
let posters = movies.poster_path
console.log(posters)
//State
const [index, setIndex] = useState(0)
//UseEffect
useEffect(() => {
setTimeout(
() =>
setIndex((prevIndex) =>
prevIndex === posters.length - 1 ? 0 : prevIndex 1
),
delay
);
return () => {};
}, [index]);
return (
<div className="slideshow">
<div className="slideshowSlider" style={{ transform: `translate3d(${-index * 100}%, 0, 0)` }}>
{posters.map((poster, index) => (
<img src={poster} className="slide" key={index} style={{ poster }}/>
))}
</div>
{/* <div className="slideshowDots">
{posters.map((_, index) => (
<div key={index} className="slideshowDot"></div>
))}
</div> */}
</div>
);
}
export default Slideshow
CodePudding user response:
From comments on the question...
When the 'movies' state is passed to the header through to the slideshow it is not undefined. When I log 'movies' it works.
Indeed. It's an array. That array is initially empty here:
const [movies, setMovies] = useState([])
And presumably your AJAX operation sets it to a potentially non-empty array.
The problem is when I try to log a property of that movie it gives me undefined. eg: movies.poster_path returns 'undefined'
What is "that movie"? movies
is an array. It's a collection of zero or more "movies". If nothing else, look at the semantics of your variable. It's called movies
, not movie
.
The code has no way of knowing which specific element from the collection you are referring to unless you tell it. An array has no property called poster_path
, but an object in the array could:
movies[0].poster_path
(This of course assumes there is at least one object in the array. There may be none.)
In fact, you're even expecting poster_path
to also be an array here:
let posters = movies.poster_path
// and later...
posters.map((poster, index) => (
So... Is your data an array or isn't it? Sometimes you think it is, sometimes you think it isn't. It has to be one or the other, it can't simultaneously be both.
If movies
is indeed an array (and the code indicates that it is), and if objects within that array have a property called poster_path
, and if you expect posters
to be an array of that property (and the code indicates that you do), then make it an array of that property:
let posters = movies.map(m => m.poster_path)
Overall you just need to be aware of what data is in your variables. Be aware of what is a collection of objects and what is a single instance of an object.
CodePudding user response:
movies
is initially an array and movies.poster_path is definitely undefined
. you may want to use a useEffect
hook to monitor when the data is updated.
so change posters to useState
and set the state when movie is updated with a useEffect.
const [posters, setPosters] = useState("")
useEffect(() => {setPosters(movies.poster_path)},[movies])
Hope this helps.