Parth Tiwari
Parth Tiwari

Reputation: 486

How to update object using index value in Reactjs?

I am having a onChange function i was trying to update the array options by index wise and i had passed the index to the function.

Suppose if i am updating the options array index 0 value so only that value should be update rest should remain as it is.

Demo

Here is what i tried:

import React from "react";
import "./styles.css";

export default function App() {
  const x = {
    LEVEL: {
      Type: "LINEN",
      options: [
        {
          Order: 1,
          orderStatus: "INFO",
          orderValue: "5"
        },
        {
          Order: 2,
          orderStatus: "INPROGRESS",
          orderValue: "5"
        },
        {
          Order: 3,
          orderStatus: "ACTIVE",
          orderValue: "9"
        }
      ],
      details: "2020  N/w UA",
      OrderType: "Axes"
    },
    State: "Inprogress"
  };

  const [postdata, setPostData] = React.useState(x);

  const handleOptionInputChange = (event, idx) => {
    setPostData({
      ...postdata,
      LEVEL: {
        ...postdata.LEVEL.options,
        [event.target.name]: event.target.value
      }
    });
  };

  return (
    <div className="App">
      {postdata.LEVEL.options.map((item, idx) => {
        return (
          <input
            type="text"
            name="orderStatus"
            value={postdata.LEVEL.options[idx].orderStatus}
            onChange={e => handleOptionInputChange(e, idx)}
          />
        );
      })}
    </div>
  );
}

Suppose if i want to add the objects in another useState variable for all the updated options only, will this work?

const posting = {
        "optionUpdates": [],
    }

    const [sentdata , setSentData] = useState(posting);
    
    setSentData({
            ...sentdata,
            optionUpdates: [{
            ...sentdata.optionUpdates,
            displayOrder: event.target.value
        }]
    })

Upvotes: 1

Views: 992

Answers (2)

gdh
gdh

Reputation: 13682

Basically, you need to spread properly, use callback approach to set state etc.

Change your handler to like this.

Working demo

const handleOptionInputChange = (event, idx) => {
    const target = event.target; // with callback approach of state, you can't use event inside callback, so first extract the target from event.
    setPostData(prev => ({ // prev state
      ...prev, // spread prev state
      LEVEL: { //update Level object
        ...prev.LEVEL,
        options: prev.LEVEL.options.map((item, id) => { // you need to loop thru options and find the one which you need to update.
          if (id === idx) { 
            return { ...item, [target.name]: target.value }; //spread all values and update only orderStatus
          }
          return item;
        })
      }
    }));
  };

Edit Added some comments to code and providing some explanation.

You were spreading postdata.LEVEL.options for LEVEL which is incorrect. For nested object you need to spread each level.

Upvotes: 1

Julien Deniau
Julien Deniau

Reputation: 5040

Apparently, your event.target.name is "orderStatus", so it will add an "orderStatus" key to your postData.

You might want to do something like this:

const handleOptionInputChange = (value, idx) => {
  setPostData(oldValue => {
    const options = oldValue.LEVEL.options;
    options[idx].orderStatus = value;

    return {
      ...oldValue,
      LEVEL: {
        ...oldValue.LEVEL,
        options
      }
    };
  });
};

return (
  <div className="App">
    {postdata.LEVEL.options.map((item, idx) => {
      return (
        <input
          type="text"
          name="orderStatus"
          value={postdata.LEVEL.options[idx].orderStatus}
          onChange={e => handleOptionInputChange(e.target.value, idx)}
        />
      );
    })}
  </div>
);

See this demo

Upvotes: 0

Related Questions