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
]);