1

I'm trying to make an axios.get call and set a const called movies held in the component state with the data that comes back from that call. However, it appears that the API call is not working. The data from the API call never populates the movies const and in return, another function, which relies on the data from said const keeps coming back undefined, breaking the code. Currently, I have the movies const initialized as an empty array, which I thought could be the problem. I tried changing the code and initializing to both an empty string and null. Neither of those changes produced different results. The movies const is still coming back as an empty array. Can someone spot my mistake?

import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";

const initialMovie = {
    id: '',
    title: '',
    director: '',
    metascore: '',
    stars: [],
  };

const UpdateMovie = () => {
    const [movies, setMovies] = useState([]);
    const [specificMovie, setSpecificMovie] = useState(initialMovie);
    const { id } = useParams();

    useEffect(() => {
        axios.get('http://localhost:5000/api/movies')
        .then(res => setMovies(res.data))
        .catch(err => console.log(err))
    }, [])

    console.log(movies);

    useEffect(() => {
        const movieToUpdate = movies.find(m => `${m.id}` === id);

        if (movies !== []) {
            setSpecificMovie(movieToUpdate);
        }
    }, [movies, id])

    const handleChanges = e => {
        e.persist();
        let value = e.target.value;

        setSpecificMovie({
            ...specificMovie,
            [e.target.name]: value
        })
    };

    return (
        <div>
            <form>
                <input type="text" name="title" className="input" value={movieToUpdate.title} />
                <input type="text" name="director" className="input" value={movieToUpdate.director} />
                <input type="text" name="metascore" className="input" value={movieToUpdate.metascore} />
                <button>Submit</button>
            </form>
        </div>
    )
};

export default UpdateMovie;



Jevon Cochran
  • 1,565
  • 2
  • 12
  • 23

1 Answers1

1

Your code is fine (the fetch part). The movie update useEffect is wrong:

useEffect(() => {
    const movieToUpdate = movies.find(m => `${m.id}` === id);

    if (movies !== []) {
        setSpecificMovie(movieToUpdate);
    }
}, [movies, id])

The movies !== [] check will always be false, because [] is equal as new Array() (always a new reference). You need a check like this:

if (movies.length !== 0 && movieToUpdate)

This check that your movies have something in them and that movieToUpdate is not undefined (find will return undefined if not found).

You could even simplify to only check:

if (movieToUpdate)
Kaca992
  • 2,211
  • 10
  • 14
  • 1
    I'm going to accept your answer as the correct answer with the caveat that the bigger problem was actually the value in my inputs. Due to closure, the inputs don't have access to movieToUpdate because that const was declared inside the useEffect hook. I implemented your change and switched the values to specificMovie.name/specificMovie.director/specificMovie.metascore and that solved the problem. – Jevon Cochran Jan 30 '20 at 20:08