fstennet
fstennet

Reputation: 1602

TypeError updating a nested array of Objects

I was hoping to be able to update a state object from this:

this.state = {
          items: {},
}

to this:

this.state = {
          items: {
              2020-01-01: [
                     {'text': 'Some text', 'start_time': 'Some time'},
                     {'text': 'Some text', 'start_time': 'Some time'}],
              2020-01-02: [
                     {'text': 'Some text', 'start_time': 'Some time'},
                     {'text': 'Some text', 'start_time': 'Some time'}]
          }
}

by using spread operator:

//response from the API
response.items.map((item, index) => {
  this.setState(prevState => ({
           items: {
             ...prevState.items,
             [item.time]: [
               ...prevState.items[item.time], 
               {
                'text': item.summary,
                'start_time': item.start_time
               }]
           }
  }))
});

but that generates a TypeError:

TypeError: Invalid attempt to spread non-iterable instance

The purpose of updating the state object in such way is to render this component with data pulled from an API. But I can't seem to get it right.

Upvotes: 2

Views: 109

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370679

No matter what time is in the .map, it does not exist as a property of items in the initial state, the first time this code is run:

const initialState = {
  items: {},
};

const time = '2020-01-01';
const newState = ({
  items: {
    ...initialState.items,
    [time]: [
      ...initialState.items[time],
      {
        'text': item.summary,
        'start_time': item.start_time
      }
    ]
  }
});

Alternate with the empty array instead, so that it can be spread properly:

...(initialState.items[time] || []),

const initialState = {
  items: {},
};

const item = { summary: 'foo', start_time: 'bar' };

const time = '2020-01-01';
const newState = ({
  items: {
    ...initialState.items,
    [time]: [
      ...(initialState.items[time] || []),
      {
        'text': item.summary,
        'start_time': item.start_time
      }
    ]
  }
});
console.log(newState);

Upvotes: 4

Related Questions