简体   繁体   中英

An array with objects, within an object is undefined

I have an array that contains objects, inside an object. I can console.log the first object and the array, but when i try to access the objects within the array or use the map-function on the array i get an error that says "Can't read property of undefined".

I have thoroughly searched SO and other sites for similar problems and found some but no answers seems to work for me.

The object looks like this:

{ 
  answers: [{…}],
  createdAt: "2019-01-23T10:50:06.513Z", 
  nested: {kebab: "jjjj", sås: 2, sallad: "kkk"},
  text: "weaxcc",
  /* etc... */
}

And i can access it using: this.state.data

I want to access objects inside the answers-array like:

this.state.data.answers[0].text

or even :

this.state.data.answers.map().....

But that gives me 'Cannot read property '0' of undefined. The answers-array is not empty.

Any help is appreciated!

EDIT This is how the objects ends up in my state.

getQuestionFromDb = () => {
    axios.get(`http://localhost:3000/questions/${this.state.id}`)
    .then(res => this.setState({
      data: res.data
    }));
  };

This function is called in the ComponentDidMount()-method.

Here is my render function (the console.log is causing the error):

render() {
return (
  <div className="main-content">
    <h2>{this.state.data.text} </h2>
    {console.log(this.state.data.answers[0].text)}
    <p>Introducing <strong>{this.state.id}</strong>, a teacher who loves teaching courses about <strong>{this.state.id}</strong>!</p>
    <input
    type="text"
    onChange={e => this.setState({ message: e.target.value })}>
    </input>
    <button onClick={() => {this.handleAnswerPost(this.state.message)}}>Answer</button>
  </div>
    );
  }
}

componentDidMount is getting called when your component becomes part of the DOM but the call you do to populate your state is async due to XHR, which may take 100-300ms more to get the data in your component, so this.state.data.answers won't be available in the initial render() cycle.

since you mentioned using a loop, I suggest setting an initial state shape like

this.state = { 
  data: { 
    answers: [] 
  } 
}

your initial render won't have anything to loop but as soon as it resolves the data and sets the new state, it will render correctly.

alternatively you can

return this.state.data.answers.length ? loopItemsHere : <div>Loading..</div>

obviously, loopItemsHere can be anything you write to show the answers.

This might not be working when data doesnt contain answers[] at the very first mount for a component.

You may wanna check for your array's existance as following:

const { data } = this.state;
data.hasOwnProperty('answers') && console.log(data.answers[0]);

The reason we can't access object key in Javascript, usually it is because the variable/value is not the type of Object. Please ensure that this.state.data type is Object. You can try to console.log( typeof this.state.data ) . We should expect that it is output object . If the type is string , you should parse it first with JSON.parse() .

There may be a number of reasons that could cause the data object not to be shown:

  • The object was not in state at the time of it being called. This may be caused by an async operator not loading in the data. Eg if you are requesting for the object from the database, chances are that at the time of making a call to retrieve the data ( this.state.data ), the response had not been given.

  • The object may not have been parsed into string. Try running console.log(typeof this.state.data) . If the output is string , then you may have to parse it. If the output is undefined , then point one is valid

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM