简体   繁体   中英

ReactJS: Appending new object to an existing array with spread

I have this array object to begin with

[
  {
    "name": "child",
    "pax": {}
  }
]

I wish to append new property which is an array. then I want to update/insert new object into that array. But something is wrong with my code

function App() {
  const [num, setNum] = useState(0);
  const [arr, setArr] = useState([
    {
      name: "child",
      pax: {}
    }
  ]);

  function appendage({ id, age }) {
    const toSaveArr = arr.map(o => {
      if (o.name === "child") {
        return {
          ...o,
          age: o.age
            ? o.age.map(o2 => {
                if (o2.id === id) {
                  return {
                    id: o2.id,
                    age
                  };
                }
                console.log("o2", o2);
                //something is wrong here
                //why is it not adding new object?
                return [
                  ...o2,
                  {
                    id,
                    age
                  }
                ];
              })
            : [{ id, age }]
        };
      }
      return o;
    });

    setArr(toSaveArr);
  }

  return (
    <div className="App">
      <h1>{num}</h1>
      <button
        onClick={() => {
          setNum(num + 1);

          appendage({
            id: num + 1,
            age: num + 1
          });
        }}
      >
        add
      </button>
      <button>update age where id equal to 2</button>
      <pre>{JSON.stringify(arr, null, 2)}</pre>
    </div>
  );
}

https://codesandbox.io/s/pedantic-mclean-107q2

I think I've used spread operator wrongly here.

The problem is that the function you pass into map returns an array, but that is not how map works. You can only change existing objects in the array, but not add new ones. What you can do is use for example find to search for the object in the array and check if the result is undefined .

const result = o.age.find(o2 => o2.id === id);
if (result) {
    result.age = age;
} else {
    o.age.push({ id: o2.id, age: age });
}

you can use find method in your array to find specific value which is here "child" :

import React, { useState, useDebugValue } from "react";
import styled from "styled-components";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [num, setNum] = useState(0);
  const [arr, setArr] = useState([
    {
      name: "child",
      pax: []
    }
  ]);

  function appendage({ id, age }) {
    var newarr = arr;
    var add = {
      id: id,
      age: age
    };
    newarr.find(el => el.name === "child").pax = [
      ...newarr.find(el => el.name === "child").pax,
      add
    ];

    setArr(newarr);
  }

  return (
    <div className="App">
      <h1>{num}</h1>
      <button
        onClick={() => {
          setNum(num + 1);

          appendage({
            id: num + 1,
            age: num + 1
          });
        }}
      >
        add
      </button>
      <button>update age where id equal to 2</button>
      <pre>{JSON.stringify(arr, null, 2)}</pre>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

we check to see if there is already an age object, if yes, we add a new object using spread operator; if no, we insert the object;

relevant code :

import React, { useState } from "react";
import styled from "styled-components";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [num, setNum] = useState(0);
  const [arr, setArr] = useState([
    {
      name: "child",
      pax: {}
    }
  ]);

  function appendage({ id, age }) {
    console.log("inside appendage with ", id, " and age:", age);
    const toSaveArr = arr.map(o => {
      if (o.name === "child") {
        if (o.age) {
          console.log("age exists");
          o.age = [
            ...o.age,
            {
              id: id,
              age: age
            }
          ];
          console.log("O", o);
        } else {
          o.age = [
            {
              id: id,
              age: age
            }
          ];
          console.log("O", o);
        }
        /*return {
          ...o,
          age: o.age
            ? o.age.map(o2 => {
                if (o2.id === id) {
                  return {
                    id: o2.id,
                    age
                  };
                }
                console.log("o2", o2);
                //something is wrong here
                //why is it not adding new object?
                return [
                  ...o2,
                  {
                    id,
                    age
                  }
                ];
              })
            : [{ id, age }]
        };
      */
      }
      return o;
    });

    setArr(toSaveArr);
  }

  return (
    <div className="App">
      <h1>{num}</h1>
      <button
        onClick={() => {
          setNum(num + 1);

          appendage({
            id: num + 1,
            age: num + 1
          });
        }}
      >
        add
      </button>
      <button>update age where id equal to 2</button>
      <pre>{JSON.stringify(arr, null, 2)}</pre>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

working codesandbox here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM