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)
}

4 thoughts on “How to add more objects to Array Object state using setState?”

  1. 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])
          }
    
    Reply
  2. 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)
      }, [])
    }
    
    Reply
  3. 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.

    Reply
  4. 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...
    };
    
    Reply

Leave a Comment