Citanaf
Citanaf

Reputation: 464

Returning a data object from state - Cannot read property '0' of undefined

I'll preface this by saying it's only my second day working with react and I'm no expert in coding either. I would appreciate any answers to this to be explained as such. Any and all responses are however greatly valued.

I am trying to understand the relationship between the state and render(). I have defined a data object called myDataObj. The App component grabs some variables in the constructor. I create a variable called someData which takes a dataobject and myVar which is an integer. The render function is executed the first time. Each of my console.logs are logged to the console. The componentDidMount function is then executed after the render, then the render is ran again due to the setState method.

My question is why can I not get the two lines that I have commented out to pull the value from the state? I am able to directly access those variable (within scope) by referencing them directly: myDataObj.myData[0]. I can access the myVar variable via the state as shown in this.state.myVar.

When trying to push a new item into myDataObj via someData.myData.push({name:'Item 4'}); I get a 'someData' is not defined.

When trying to log the first element of the variable via {console.log(this.state.someData.myData[0])} I get a 'Cannot read propert '0' of undefined.

Hopefully I was able to articulate the problem correctly. The code is below.

Thank you

import React, {Component} from 'react';
import './App.css';

let myDataObj = {
  myData: [
    {name:'Item 1'},
    {name:'Item 2'},
    {name:'Item 3'}
    ]
};

let myVar = 2


class App extends Component {
  constructor() {
    super();
    this.state = {someData: {}, myVar}
  }
  componentDidMount() {
      myVar = myVar + 1;
      myDataObj.myData.push({name:'Item 4'});
      // someData.myData.push({name:'Item 4'});    this doesn't work... 'someData' is not defined
      this.setState({someData: myDataObj, myVar});

  }
  render () {
    return(
      <div className="App">
        {console.log(myVar)}   {/* Logs a 2 then 3 */}
        {console.log(this.state.myVar)}   {/* Logs a 2 then 3 */}
        {console.log(myDataObj.myData[3])}   {/*Logs undefined then 'Item 4' */}
        {/* {console.log(this.state.someData.myData[0])} */} {/*TypeError: Cannot read property '0' of undefined */}
      </div>
    );
  }
}

export default App;

Upvotes: 1

Views: 122

Answers (3)

Gaurab Kc
Gaurab Kc

Reputation: 851

About your first log statement, someData is undefined because it is a state variable so it needs to be accessed as this.state.someData. Still pushing items directly into the state is not a good practice. Just for the sake of your log statement, your state needs to be initialized like i have done below for it to run correctly.

 this.state = {
    someData: {
        myData: []
    },
    myVar
 }

This should solve your second log statement as well. Your state needs to be initialized as above if you want to log this.state.someData.myData[0] on your first render because myData array inside someData is not defined until your setState in componentDidMount runs.

Upvotes: 1

Berouminum
Berouminum

Reputation: 530

You might want to checkout React's component lifecycle. State and Lifecycle

ComponentDidMount get's executed after mounting, e.g. after the component has been rendered once. During your first render this.state.someData.myData is undefined. Accessing a property of undefined results in a TypeError.

Move your variable directly to your state:

this.state = {
      myData: [
        {name:'Item 1'},
        {name:'Item 2'},
        {name:'Item 3'}
      ], 
      myVar : 2
}

Upvotes: 2

Garry
Garry

Reputation: 534

Not sure why you are declaring variables outside the class and then using it as its state. I would do like :-

import React, {Component} from 'react';
import './App.css';


class App extends Component {
  constructor() {
    super();
    this.state = {
      myData: [{name:'Item 1'},
        {name:'Item 2'},
        {name:'Item 3'}], 
      myVar : 2}
  }
  componentDidMount() {
      //myVar = myVar + 1;
     // myDataObj.myData.push({name:'Item 4'});
      // someData.myData.push({name:'Item 4'});    this doesn't work... 'someData' is not defined
      this.setState({myData: [...this.state.myData, {"name" : 4}], 

    myVar : this.state.myVar + 1});

  }
  render () {
    return(
      <div className="App">
        {console.log(this.state.myVar)} 
        {console.log(this.state.myData[3])} 
      </div>
    );
  }
}

export default App;

Upvotes: 2

Related Questions