skip to Main Content

I am using react, and I got a nested object like this:

const obj = useRef({
    category1: [
      { title: { name1: 'value1' } },
      { title: { name2: 'value2' } }
    ],
    category2: [
      { title: { name3: 'value3' } },
      { title: { name4: 'value4' } }
    ]
  });

When I trying to update the category1 by adding a newTitle object in category1[index], the title object got replaced.

what I want:

const obj = useRef({
   category1: [
     { title: { name1: 'value1' } },
     { title: { name2: 'value2' }, newTitle: { name5: 'value5' } }
   ],
   category2: [
     { title: { name3: 'value3' } },
     { title: { name4: 'value4' } }
   ]
 });

what I got:

const obj = useRef({
    category1: [
      { title: { name1: 'value1' } },
      { newTitle: { name5: 'value5' } }
    ],
    category2: [
      { title: { name3: 'value3' } },
      { title: { name4: 'value4' } }
    ]
  });

I tried few different ways and none of it works.

const titleVar = 'newTitle';

const nameVar = 'name5';

const valueVar = 'value5';

obj.current[ctg][index][titleVar] = { [nameVar]: valueVar };


obj.current = {
                    ...obj.current,
                    [ctg]: [
                        ...obj.current[ctg].slice(0, index),
                        {
                            ...obj.current[ctg][index],
                            [titleVar]: { [nameVar]: valueVar }
                        },
                        ...obj.current[ctg].slice(index + 1)
                    ]
                };

const temp = {...obj.current[ctg][index],
               [titleVar]: { [nameVar]: valueVar } };
 obj.current = temp;

2

Answers


  1. When updating the nested object, you need to make sure to preserve the existing properties of the object while adding new properties. you aren’t using spread operator properly. here is the snippet which will get you the result you desire. click on update Object button to update the obj.

    // Get a hook function
    const {useState} = React;
    const {useRef} = React;
    const MyComponent = () => {
      const [obj, setObj] = useState({
        category1: [
          { title: { name1: 'value1' } },
          { title: { name2: 'value2' } }
        ],
        category2: [
          { title: { name3: 'value3' } },
          { title: { name4: 'value4' } }
        ]
      });
    
      const ctg = 'category1';
      const index = 1;
      const titleVar = 'newTitle';
      const nameVar = 'name5';
      const valueVar = 'value5';
    
      const updateObject = useRef(() => {
        const updatedObj = {
          ...obj,
          [ctg]: obj[ctg].map((item, i) => {
            if (i === index) {
              return {
                ...item,
                [titleVar]: { ...item[titleVar], [nameVar]: valueVar }
              };
            }
            return item;
          })
        };
    
        setObj(updatedObj);
      });
    
      return (
        <div>
          <h2>Object State:</h2>
          <pre>{JSON.stringify(obj, null, 2)}</pre>
          <button onClick={updateObject.current}>Update Object</button>
          <h2>Updated Object State:</h2>
          <pre>{JSON.stringify(obj, null, 2)}</pre>
        </div>
      );
    };
    
    
    
    // Render it
    ReactDOM.createRoot(
        document.getElementById("root")
    ).render(
        <MyComponent />
    );
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
    Login or Signup to reply.
  2. I don’t know anything about React, but I got the results you expected with this Vanilla Javascript code, which looks a lot like one of the things you tried:

    const obj = ({
        category1: [
            { title: { name1: 'value1' } },
            { title: { name2: 'value2' } }
        ],
        category2: [
            { title: { name3: 'value3' } },
            { title: { name4: 'value4' } }
        ]
    });
    const ctg = 'category1'
    const idx = 1
    const titleVar = 'newTitle'
    const nameVar = 'name5'
    const varVal = 'value5'
    obj[ctg][idx][titleVar] = { [nameVar]: varVal }
    console.dir(JSON.stringify(obj))
    console.dir(obj)
    

    Which is to say:

    {
        "category1": [
            {"title": {"name1": "value1"}}, 
            {"title": {"name2": "value2"}, "newTitle": {"name5": "value5"}}
        ], "category2": [
            {"title": {"name3": "value3"}}, 
            {"title": {"name4": "value4"}}
        ]
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search