0

I'm requesting data from an API within my react class component. Within my fetchData method, I setState to a key called data that initially is only an empty object. Withing the fetchData method, the object is filled with the data result from the API. I spread the result into the data object and within the object, I add a "directors" key that is an array that gets created because of the filter method. My issue is that I need the length of the directors array but this.state.data.directors.length caused an error saying that it's undefined. However, this.state.data.directors returns to me the array successfully and I can see within the console when I open the array up that the length property is the number that I actually need. Here is a version of my code.

constructor(){
        super();
        this.state={
            data: {},
        };
    }

    fetchData = async movieId => {

        try{
            const endpoint = `${API_URL}movie/${movieId}?api_key=${API_KEY}`;
            const result = await(await fetch(endpoint)).json();
            const creditsEndpoint = `${API_URL}movie/${movieId}/credits?api_key=${API_KEY}`;
            const creditsResult = await (await fetch(creditsEndpoint)).json();
            const directors = creditsResult.crew.filter(member => member.job === 'Director');

            this.setState({
                data: {
                    ...result,
                    actors: creditsResult.cast,
                    directors
                }
            }, () => {
                localStorage.setItem(`${movieId}`, JSON.stringify(this.state.data));
            });

        }catch(error){
            this.setState({error: true});
            alert(error);
        }
        this.setState({loading: false});
    }

    componentDidMount(){
        const {movieId} = this.props.match.params;

        if(localStorage.getItem(`${movieId}`)){
            console.log("grabbing from localStorage" + " " + movieId);
            this.setState({
                data: JSON.parse(localStorage.getItem(`${movieId}`))
            });
        } else {
            console.log("Grabbing from API");
            const {movieId} = this.props.match.params;
            this.setState({loading: true});
            this.fetchData(movieId);
        }
    }

    render(){
        const {data} = this.state;
        console.log(this.state.data.directors.length);
        return(

I expected to get the length property from the directors array since console.logging the directors array return an array with an object in it.

2
  • 2
    Looks like the directors key is set asynchronously in componentDidMount, so it likely won't actually be available until the subsequent render. You'll want to guard against this somehow, perhaps rendering some kind of "Loading..." indicator if this.state.data.directors is undefined Commented Feb 22, 2020 at 22:19
  • 1
    There are two things you can do. Either define initial state with an empty array, or prevent rendering until the data is populated (for example return a preloader component) Commented Feb 22, 2020 at 22:29

1 Answer 1

2

You are not defining the initial state of the directors array. As a result of this, directors is undefined until after the API request has been resolved

this.state = {
  data: {
    directors: []
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.