SwethaG
SwethaG

Reputation: 173

Nested map function on parsed JSON data

I am receiving a JSON data from database which is [{"table_cols":["id","stud_name","stud_school"]}].

 console.log("Response is: " + resp._bodyText); {/*Response is: [{"table_cols":["id","stud_name","stud_school"]}]*/}

         let parsedData = JSON.parse(resp._bodyText);
         console.log(parsedData) //Object
        this.setState({...this.state,cols_of_sel_tab:parsedData})


        for(let i=0; i<this.state.cols_of_sel_tab.length;i++)
        {
            cols = [];
            console.log(this.state.cols_of_sel_tab[i])
            let cols = this.state.cols_of_sel_tab[i]
            console.log("WOW")
            for (let j = 0; j<cols.length; j++){
                console.log(cols[j])
            }
        }

Output: {table_cols: Array(3)} WOW

Expected: To iterate through the inner for loop Desired output is: id, stud_name,stud_school

Tried: using forEach instead of inner for loop Error: ...\node_modules\react-native\Libraries\ReactNative\YellowBox.js:82 Possible Unhandled Promise Rejection (id: 0): TypeError: Cannot read property 'forEach' of undefined TypeError: Cannot read property 'forEach' of undefined

I need help!

Upvotes: 0

Views: 140

Answers (3)

Dmitry Birin
Dmitry Birin

Reputation: 1614

1. Solution to your question

The main problem why you (somehow without syntax error and not getting the empty state problem) get the

Output:{table_cols: Array(3)} WOW

and not the array items, because of the model of your response

[
  {"table_cols":
      ["id",
      "stud_name",
      "stud_school"]
  }
]

So, instead of

let cols = this.state.cols_of_sel_tab[i]

should be

let cols = this.state.cols_of_sel_tab[i].table_cols

And input will be: {table_cols: Array(3)} WOW id stud_name stud_school

2. Syntax Error

cols = [];
let cols = this.state.cols_of_sel_tab[i]

You're trying to assign empty array to the variable, that not defined. In this particular example you could just amend the first row

3. State handling

In your code example you've got two goals: update the state with new data and use the new data for output. Cause state updates are asynchronous is much safer to manipulate and output the data you already have right away (I amended debug console output).

this.setState({cols_of_sel_tab: parsedData})
for(let i=0; i<parsedData.length; i++) {
    let cols = parsedData.cols_of_sel_tab[i].table_cols
    for (let j = 0; j<cols.length; j++) {
        console.log(cols[j])
    }
}

Also, cause states updates are merged you can amend spread operator for this.state, like in the code above.

4.More improvements

  1. There is a map function mention in header of the question, you could use it.

    parsedData.map(
        col_of_sel => col_of_sel.table_cols.map(
            cols => console.log(cols)
        )
    )
    

    or, if you only need the table_cols of the first object:

    parsedData[0].table_cols.map(cols => console.log(cols))
    
  2. You've got different code style in your example in question: semicolon presence, differences in indentations. I recommend to use some kind of prettier to pretty up the code, so it will be easier to read.

Finally

let parsedData = JSON.parse(resp._bodyText)
this.setState({ cols_of_sel_tab: parsedData })
parsedData[0].table_cols.map(cols => console.log(cols))

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074295

State updates are asynchronous. If you want to loop through the data you've received right then, use parsedData, not this.state.cols_of_sel_tab.

Separately, never do this:

this.setState({...this.state,cols_of_sel_tab:parsedData});

If you're setting state based on your current state, you must not pass in an object; instead, you must pass in a callback function that uses the state it receives as an argument (see the linked docs for details).

But in this case, you don't need the ...this.state at all, so it would be fine if you just did this:

this.setState({cols_of_sel_tab:parsedData});

...and then (again) looped through parsedData not this.state.cols_of_sel-tab.


Separately, you have a problem with cols: You're trying to use it in a block before it's declared with let. If you'd really run that code, it would have failed with an error saying cols is not defined (because you cannot access an identifier declared with let or const within a block prior to the declaration, even if it exists in an outer scope).

Upvotes: 1

Perran Mitchell
Perran Mitchell

Reputation: 1158

The problem is a slight misunderstanding of what your JSON data represents.

If we make the JSON a little prettier:

[
    {"table_cols":
        ["id",
        "stud_name",
        "stud_school"]
    }
]

The outer square brackets represent an array. This array contains one item at index 0, which is the table_cols object. This object also contains an array, with your table col fields in.

You're running a for loop on the outer array. The first item this loop will come across is the object at index 0. To reach the table columns you'd need to either run a second for loop on the table_cols, or run the original loop on this.state.cols_of_sel_tab[0].table_cols.

Upvotes: 0

Related Questions