Home > Mobile >  Spread objects into a state array
Spread objects into a state array

Time:10-22

I am trying to spread values as objects into a state array in react, but this code causes this error:

Error:

TypeError: Invalid attempt to spread non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.

Is there a chance I can spread values from the data array into a values state array as objects, so values array would be the same as the data array?

import { useState } from "react";
import "./styles.css";

export default function App() {
  const [places, setPlaces] = useState([]);
    const [isLoaded, setIsLoaded] = useState(false);

    useEffect(() => {
        const getData = async () => {
            const q = query(collection(firestore, 'places'));

            await getDocs(q)
                .then((data) => {
                    data.forEach((item) => {
                        if (item.exists()) {
                            setPlaces((prevState) => [...prevState, ...item.data()]);
                        }
                    });
                });

            setIsLoaded(true);
        };

        getData();
    }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

CodePudding user response:

It sounds like item.data() doesn't return an iterable.

There's no need for that forEach, just use the data directly. If you need to map it (sounds like you do, calling item.data() on each item), you can use map for that:

useEffect(() => {
    const getData = async () => {
        const q = query(collection(firestore, "<collectionName>"));

        const data = await getDocs(q);
        setPlaces((prevPlaces) => [
            ...prevPlaces,
            ...data.map((item) => item.data()),
        ]);
        setIsLoaded(true);
    };

    getData();
}, []);

That spreads the new array from map, it doesn't try to spread item.data().


In a comment you've said that using data.map(/*...*/) causes:

data.map is not a function

That means data isn't an array as the question states, it's some other kind of collection with a forEach method.

If it's an array-like, you should be able to do the mapping with Array.from:

setPlaces((prevPlaces) => [
    ...prevPlaces,
    ...Array.from(data, (item) => item.data()), // ***
]);

If it's not an array-like, then worst case, you can use forEach to create a new array:

const mapped = [];
data.forEach((item) => mapped.push(item.data()));
setPlaces((prevPlaces) => [
    ...prevPlaces,
    ...mapped
]);
  • Related