react Push Object to array from list of arrarys

Welcome to Programming Tutorial official website. Today - we are going to cover how to solve / find the solution of this error react Push Object to array from list of arrarys on this date .

I am trying to push ojbects into specific arrary from list of arrarys. I was able to push the ojbect but it creates additional arrary in root.

      const [variants, setVariants] = useState([]);
    
      const colorNameRef = useRef('');
      const sizeNameRef = useRef('');
      const sizeSkuRef = useRef('');
    
      const addEntryClick = (e) => {
        e.preventDefault();
        const newEntry = {
          colorName: colorNameRef.current.value,
          id: e.timeStamp.toFixed(0),
          sizes: []
        };
        setVariants((preEntry) => [...preEntry, newEntry]);
     
      };
    
      const handleAddSize = (index) => (e) => {
        e.preventDefault();
        console.log(index);
     
        let newSize = {
          name: sizeNameRef.current.value,
          id: sizeSkuRef.current.value
        };          
    
        setVariants([...variants, variants[index].sizes.push(newSize)]);
     
      };
    
      function handleSubmit() {
        console.log(variants);
      }
return(
    <>
          <div>
            <input type="text" ref={colorNameRef} />
            <button onClick={addEntryClick}>Add</button>
          </div>
          <div>
            {variants &&
              variants.map((variant, index) => (
                <div key={index}>
                  <div className={variant.id}>{variant.id}</div>
                  <div>{variant.colorName}</div>
                  <div className="ftw=semi" data-id={variant.id}>
                    <div>
                      <input type="text" ref={sizeNameRef} />
                      <input type="text" ref={sizeSkuRef} />
                    </div>
    
                    <button className="btn-blue" onClick={handleAddSize(index)}>
                      Add
                    </button>
                  </div>
                  {/* {variant.sizes &&
                    variant.sizes.map((size, index) => (
                      <div key={index}>{size.name}</div>
                    ))} */}
                </div>
              ))}
          </div>
          <button onClick={handleSubmit}>Submit</button>
        </>
)

the ideal result I am looking for is

[
 {colorName : 'something', id: '234234', sizes : [{}]
{colorName : 'something', id: '234234', sizes : [{}]
{colorName : 'something', id: '234234', sizes : [{}]
]

addEntryClick() to create an ojbect with colorname, id, and empty sizes of arrary and handleAddSize() to find arrary index and push ojbect to siezes

so far when I run this code, I was able to do exactly what I wanted but it some how creates addition arrary when I click on hadnleAddSize()

[
     {colorName : 'something', id: '234234', sizes : [{name: 'new', id:'2342']
    1 <-- this is created everytime I click on handleAddSize()
    ]

Answer

It seems that you want to modify an array item but if you use push, you’ll be modifying the original array(which you shouldn’t do when you use react state) and also the push result is a number that indicates the array new length, that is why you’re adding a number to the sizes array.

If you want to modify the array without mutating it, there’re multiple ways to do it, here’s one of them.

const handleAddSize = (index) => (e) => {
    e.preventDefault();
    console.log(index);

    const newSize = {
      name: sizeNameRef.current.value,
      id: sizeSkuRef.current.value
    };  

    // Returns a new modified array.
    const newModifiedArr = variants.map((item, currentIndex) => {
      // If the index matches with the current index
      if (currentIndex === index) {
        // Returns a new object with the sizes property modified to add your newSize object 
        return {
         ...item,
         sizes: [...item.sizes, newSize]
        }
      }
      // if the index does not match return the current item without modifying it.
      return item
    })        

    // Set the state with the new generated array
    setVariants([...newModifiedArr]);
};