简体   繁体   中英

How to add more objects to Array Object state using setState?

This is my initial data

const data = [
  { id: '1', name: '1' },
  { id: '2', name: '1' },
  { id: '3', name: '2' },
]

I want to loop over and:

  • Where it has name 1 add that object to stateOne
  • Where it has name 2 add that object to stateTwo

End goal both states needs to have Array of Objects inside:

  • stateOne needs to look like
[
  { id: '1', name: '1' },
  { id: '2', name: '1' }
]
  • stateTwo needs to look like
[
  { id: '3', name: '2' },
]

This is what i've tried:

const data = [
  { id: '1', name: '1' },
  { id: '2', name: '1' },
  { id: '3', name: '2' },
]

const Testing = () => {
  const [stateOne, setStateOne] = useState([])
  const [stateTwo, setStateTwo] = useState([])

  useEffect(() => {
    data.forEach((e) => {
      if (e.name === '1') {
        console.log('e', e)
        setStateOne((prevSate) => ({ ...prevSate, e }))
      }
      // if (e.name === '2') {
      //   setStateTwo(e)
      // }
    })
  }, [])

  console.log('stateOne', stateOne)
}

I'd prefer sending data as a prop to that component

You can achieve what you need by


const data = [
  { id: '1', name: '1' },
  { id: '2', name: '1' },
  { id: '3', name: '2' },
]

export default function Testing() {

  const [stateOne, setStateOne] = useState([])
  const [stateTwo, setStateTwo] = useState([])

  useEffect(() => {
    setStateOne(data.filter(e => e.name === "1"))
    setStateTwo(data.filter(e => e.name === "2"))    
    console.log('stateOne', stateOne)
    console.log('stateTwo', stateTwo)
  }, [])
}

setState functions as an assignment. Like you would normally assign a variable. That means if you want to add something to an array, you need to include that array in the assignment.

Something like this:

      if (e.name === '1') {
        console.log('e', e)
        setStateOne([...stateOne, e])
      }
      if (e.name === '2') {
         setStateTwo([...stateTwo, e])
      }

If you don't want to use filter twice for whatever reason, You can create temporary array for each one and manipulate them then update each state respectively like so:

  const [stateOne, setStateOne] = useState([]);
  const [stateTwo, setStateTwo] = useState([]);

  useEffect(() => {
    const tempArr1 = [];
    const tempArr2 = [];

    data.forEach((item) => {
      if (item.name === "1") {
        tempArr1.push(item);
      } else if (item.name === "2") {
        tempArr2.push(item);
      }
    });

    setStateOne(tempArr1);
    setStateTwo(tempArr2);
  }, []);

  console.log(stateOne);
  console.log(stateTwo); 

The problem with what you're doing is you're updating the state each time you find a match which will cause a lot of unnecessary re-renders.

You've said that data comes from some API you're querying. If so, filter the data once you get it. You can do that in a couple of ways.

With two calls to filter :

const Testing = () => {
    const [stateOne, setStateOne] = useState([]);
    const [stateTwo, setStateTwo] = useState([]);

    useEffect(() => {
        let cancelled = false;
        getTheData(data => {
            if (cancelled) {
                return;
            }
            setStateOne(data.filter(({name}) => name === "1"));
            setStateTwo(data.filter(({name}) => name === "2"));
        };
        return () => {
            // So we don't try to set setate on an unmounted component
            cancelled = true;
        };
    }, []);

    // ...use `dataOne` and `dataTwo` here...
};

Or if you don't want to make two passes through the data, a single loop:

const Testing = () => {
    const [stateOne, setStateOne] = useState([]);
    const [stateTwo, setStateTwo] = useState([]);

    useEffect(() => {
        let cancelled = false;
        getTheData(data => {
            if (cancelled) {
                return;
            }
            const stateOne = [];
            const stateTwo = [];
            for (const entry of data) {
                switch (entry.name) {
                    case "1":
                        stateOne.push(entry);
                        break;
                    case "2": // or default if you want all non-1s in `stateTwo`
                        stateTwo.push(entry);
                        break;
                }
            }
            setStateOne(stateOne);
            setStateTwo(stateTwo);
        };
        return () => {
            // So we don't try to set setate on an unmounted component
            cancelled = true;
        };
    }, []);

    // ...use `dataOne` and `dataTwo` here...
};

const data = [
    { id: "1", name: "1" },
    { id: "2", name: "1" },
    { id: "3", name: "2" }
  ];
  
  const App = () => {
    const newdata = useState(data);
    const [stateOne, setStateOne] = useState([]);
    const [stateTwo, setStateTwo] = useState([]);
  
    const Filter = () => {
      let listOne = [];
      let listTwo = [];
      newdata[0].map((it) => {
        if (it.name === "1"){
          listOne.push(it);
        }
        else if(it.name === "2"){
          listTwo.push(it)
        }
      });
      setStateOne(listOne);
      setStateTwo(listTwo);
    };
  
    useEffect(() => {
      Filter();
    }, []);

    console.log("stateOne", stateOne)
    console.log("stateTwo", stateTwo)

    return (
      // your code
    )
   
  };

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