1

I have an array of object named as options in the state using useState hook I just want to update a nested array object at a specific index.


var subOptionModel = {
        text: "test",
        price: 0,
    };
    var optionModel = {
        optionSetId: 0,
        optionName: "",
        optionPrice: 0,
        editOptionName: false,
        subOptions: [subOptionModel],
    };
    const [options, setOptions] = useState([optionModel]);

I have multiple options in options state, how can I update the state like the option at index 2 and suboption at 1 here is what I tried so for.


setOptions(
                options.map((x, index) => {
                    if (index !== optionIndex) return x;
                    x.subOptions.map((subItem, subIndex) => {
                        console.log(subItem);
                        if (subIndex !== subOptionIndex) return subItem;
                        return {
                            ...subItem,
                            text: text
                        };
                    });
                }),
            );

3 Answers 3

1

I would rather use, useReducer hook for this kind of data model. Personally, I find it more clean.

But your problem is that, you are not mutating and returning your subOptions back.

setOptions(
  options.map((x, index) => {
      if (index !== optionIndex) return x;
      x.subOptions = x.subOptions.map((subItem, subIndex) => {
          console.log(subItem);
          if (subIndex !== subOptionIndex) return subItem;
          return {
              ...subItem,
              text: text
          };
      });

      return x;
  }),
);
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, it works, can you please explain it a bit more maybe it will help someone else :)
1

I'd suggest you use an immutability library, such as immer.js. This will allow you to select precisely what you want to update within your state.

This will allow you to modify your options like this:

import produce from "immer"

const newOptions = produce(options, draftOptions => {
    draftOptions[2].subOption[1] = [whatever you want]
})

setOptions(newOptions)

Comments

0

following your solution you missed to return in the first map if index === optionIndex.

setOptions((options) => {
  return options.map((x, index) => {
    if (index !== optionIndex) return x;
    return {
      ...x,
      subOptions: x.subOptions.map((subItem, subIndex) => {
        if (subIndex !== subOptionIndex) return subItem;
        return {
          ...subItem,
          text: text
        };
      })
    }
  })
})

Otherwise you can use something like immer.js

Comments

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.