Home > Net >  Why is my state value undefined when I pass it and try use it?
Why is my state value undefined when I pass it and try use it?

Time:10-06

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.

  • Related