3

I have an object defined like this:

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

class App extends Component {

  constructor() {
    super();
    this.state = {
    lists: ["Dogs", "Cats"],
    items: {Dogs:[], Cats:[]}
    };
  }

  handleAddItem(item) {
    console.log(this.props.idName);
    console.log(item);
  }

I have the variable

console.log(this.props.idName)// output: Dogs
console.log(item);// output {name: "lofi"}  

I don't know how to update the object items{} to make it becоme like this:

items{Dogs:[{name: "lofi"}], Cats:[]}
2
  • Not answering your question, but try to keep your flat is a good practice. stackoverflow.com/questions/38842454/… Commented Jun 4, 2018 at 9:54
  • 1
    @konekoya thank you Commented Jun 4, 2018 at 10:10

3 Answers 3

1

To update a nested Array substate, you can use the spread operator to append elements

handleAddItem = item => {
  this.setState((prevState, props) => ({
    items: {
      ...prevState.items,
      [props.idName]: [
        ...prevState.items[props.idName],
        item
      ]
    }
  }))
}
Sign up to request clarification or add additional context in comments.

6 Comments

It is better to use setState with callback function in such case: reactjs.org/docs/react-component.html#setstate
From React docs - this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
yeah. for things like incrementing etc I see the point, how would your solution look like? I don't see a more "atomic" way to do it.
I get this error App.js:5 Uncaught TypeError: Cannot convert undefined or null to object
@amaj Thanks for pointing this out! Good watch! I updated the code accordingly. You example is not using the props from the updater function, so you may fix your code as well :)
|
1

What about something like that

handleAddItem(item) {
    this.setState((s, p) => ({
        items: {
            ...s.items,
            [p.idName]: s.items[p.idName].concat([item])
        }
    }))
}

Few comments:

  • setState can take function, as parameter you got old state value
  • [idName]: value dynamically updates prop idName

Comments

0

You can do something like

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

class App extends Component {

  constructor() {
    super();
    this.state = {
    lists: ["Dogs", "Cats"],
    items: {Dogs:[], Cats:[]}
    };
  }

  handleAddItem(item) {
    console.log(this.props.idName);
    console.log(item);
    let oldItems = this.state.items;
    oldItems[this.props.idName].push(item);
    // Update new state for items
    this.setState({
      items: {...this.state.items}
    })

  }

7 Comments

Am updating the previous state variable to be make it ready to update for the next state. You can see spread operator in the this.setState call which updates it how react wants. Let me update the answer to make it clear.
You can pass function in setState, where you have access to oldState and you don't have to save previous state value, check docs: reactjs.org/docs/react-component.html#setstate
This may corrupt data! The setState call would overwrite the other category!
@lipp. How so ?
@agent_hunt this.state.items gets replaced entirely. If this.state.items.Cats = [{name: 'foo'}] and idName = 'Dogs', the 'Cats' get removed. That said: I just noticed, that your are missing "one level". It is e.g. this.state.items.Cats = [{name: 'foo'}] ... and not this.state.items = [{name: 'foo'}]
|

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.