0

I've been stuck for whole day and please help me to fix it. I have a json data which like this :

[
    {
        "menu": "menu_1",
        "icon": "icon_1",
        "detail": {
            "name": "name_1",
            "phone": "phone_1"
        }
    },
    {
        "menu": "menu_2",
        "icon": "icon_2",
        "detail": {
            "name": "name_2",
            "phone": "phone_2"
        }
    },
    {
        "menu": "menu_3",
        "icon": "icon_3",
        "detail": {
            "name": "name_3",
            "phone": "phone_3"
        }
    }
]

I put them into the "data" state and My goal is I wanna change the "detail" state with certain index ( ex: state "data" with index 1 change the "detail" data )

Currently my code is :

this.setState({
  data: {
    ...this.state.data,
    detail:{
      this.state.data[1].detail:{
        "name": "billy",
        "phone": "893823839"
      }
    }
  }
})

That setState is clearly wanna change the state with certain index but fail.. How do I supposed to do?

Billy
  • 95
  • 9
  • Your `data` on top is an array and on the bottom you're converting it to an object. Which type do you want? There's no need to do this inside the `setState` call. Make a copy of the data structure, set the key to what you want, then call `setState` with the new object. – ggorlen Aug 11 '20 at 16:08
  • 1
    Does this answer your question? [How to update nested state properties in React](https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react) – Anurag Srivastava Aug 11 '20 at 16:08
  • I want array data just like in the json data on the top – Billy Aug 11 '20 at 16:09
  • @ggorlen I want to setState dynamically (ex: value from input). And update the data index 1 value – Billy Aug 11 '20 at 16:25
  • Can you post a sample of what you want to achieve(result). – devd Aug 11 '20 at 16:37

2 Answers2

1

I guess this is what you're looking for, we could replace an element inside an array using splice :

const index = 1;

this.setState({
  data: [...this.state.data].splice(index, 1, {
    ...this.state.data[index],
    details: { name: "billy", phone: "893823839" },
  }),
});

Update: we could use slice also to make an immutable update with index :

this.setState({
  data: [
    ...this.state.data.slice(0, index),
    {
      ...this.state.data[index],
      details: { name: "billy", phone: "893823839" },
    },
    ...this.state.data.slice(index + 1, this.state.data.length),
  ],
});

could you try it ? this is an example that i tested using splice:

const items = [{ id: 1 }, { id: 2 }, { id: 3 }];

const indexToBeModified = 1; // { id: 2 } ==> { foo: "foo", id: 2 }

items.splice(indexToBeModified, 1, { ...items[indexToBeModified], foo: "foo" });

console.log("items", items);
Lafi
  • 1,310
  • 1
  • 15
  • 14
  • You should provide the index of the element to be modified, me i used index = 1 for example .. – Lafi Aug 11 '20 at 16:34
  • Looks like first example is doesn't work but I tried the second example and set the object into setState and it works! Thank you @Lefi Tarik – Billy Aug 11 '20 at 16:48
  • ahh now the setState with slice you update it works like charm! thankss – Billy Aug 11 '20 at 16:53
1

Here is a little modified example. It uses prevState to prevent any unwanted changes that may happen when directly interacting with this.state.

import React, { Component } from "react";

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      data: [
        {
          menu: "menu_1",
          icon: "icon_1",
          detail: {
            name: "name_1",
            phone: "phone_1"
          }
        },
        {
          menu: "menu_2",
          icon: "icon_2",
          detail: {
            name: "name_2",
            phone: "phone_2"
          }
        },
        {
          menu: "menu_3",
          icon: "icon_3",
          detail: {
            name: "name_3",
            phone: "phone_3"
          }
        }
      ]
    };
    this.modifyData = this.modifyData.bind(this);
  }

  modifyData(index) {
    this.setState((prevState) => {
      prevState.data[index].detail={
        name: "billy",
        phone: "893823839"
      };
      return {
        data: [prevState.data]
      };
    },()=>{console.log(this.state.data)});
  }
  render() {
    return (
      <button onClick={() => this.modifyData(0)}>Click to modify data</button>
    );
  }
}

Here is a code sandbox reference.

Pramod Mali
  • 1,588
  • 1
  • 17
  • 29