0

As a practice project, I've started building a small Pokedex app in React.

import React, { Component} from 'react';
import './App.css';
import Card from './components/card/Card.component';

class App extends Component{
    constructor(){
        super();
        this.state = {}
    }


    componentDidMount(){
        let pokeDataArr = []

        const getPokemonData = async() => {
            const dataResponse = await fetch(
                'https://pokeapi.co/api/v2/pokemon?limit=10'
            );
            const dataArr = await dataResponse.json();

            const dataArr2 = await dataArr.results.forEach(i => {
                fetch(i.url)
                .then(dataResponse => dataResponse.json())
                .then(json => pokeDataArr.push(json))
            }) 

            this.setState({ pokeDataArr }, () => console.log(this.state))
        }

        getPokemonData();
    }

    render(){
        return(
            <div>Pokedex!</div>
        )
    }
}

I'm having trouble accessing data from a specific index in an array.

When I log the entire state object to the console, I can see all the data I have retrieved from the AJAX call.

this.setState({ pokeDataArr }, () => console.log(this.state))

And this is the result in the console: console result

However, if I try to log out data from an index in the array with:

this.setState({ pokeDataArr }, () => console.log(this.state.pokeDataArr[0]))

I get "undefined" in the console: console result 2

As far as I'm aware, whatever function you run in the this.setState method's callback, it should run after setState has finished.

My goal is to use the data from this.state.pokeDataArr to make cards that display the info of each individual pokemon, but it seems like I'm stuck until I find a way to extract the data from the array and I have no clue what I'm missing.

Thank you for your time.

1
  • what happens if you console.log(this.state[0]) instead? Commented Jun 19, 2020 at 18:35

2 Answers 2

2

I think you messed up with your react state. Usually, what people do is they set up their react state as an object with other elements (arrays, objects, strings, whatever) inside it. This looks something like this:

 constructor(){
        super();
        this.state = {
           myObject: {},
           somethingElse: "",
           anArray: []
        }
 }

This enables you to access parts of your state like this: this.state.myObject for instance. (this would return {})

In your example, you defined your state as an empty object.

constructor(){
    super();
    this.state = {}
}

And later, you set this object to an object, with an array inside:

this.setState({ pokeDataArr });

This will set your state to this: {[(your array)]} To prevent this initialize your state like this:

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

And set your values like this:

this.setState({ pokeDataArr: pokeDataArr }, () => console.log(this.state.pokeDataArr[0]))

read more here: https://reactjs.org/docs/state-and-lifecycle.html

Sign up to request clarification or add additional context in comments.

5 Comments

actually, if you want, you could now (after your state has been correctly initialized) use the same code you used before, since javascript automatically understands, that you want to update "pokeDataArr" if your variable has the same name
Thanks for the response Tim! Thing is, that was actually how I wrote my code initially. Even with declaring the variable in the state, it still gives me the same result unfortunately.
really? I almost cannot believe this.. can you try again, just to verify it's truly not working?
Yeah, tried it again, same results. It's so weird that I can log out the entire 'this.state.pokeDataArr' array, but when I add the square brackets with an index, it just logs 'undefined'. I somehow feel like there's some asynchronous stuff happening behind the scenes, that I don't understand yet, that's causing the problem.
what happens if you put the console.log in the render() function? because if it was an async error you would get the correct result here
0

You'll need to use updater to use the callback instead of plain state update:

this.setState(
  () => ({ pokeDataArr }), 
  () => console.log(this.state.pokeDataArr[0])
)

Read the note from the docs in the linked example:

Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the current state, we recommend using the updater function form

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.