I have a state array in react which I am trying to add items from a smart contract
The state array is initialised as
const [products, setProducts] = useState([]);
- and 2. below did not work, but 3. does work when the array is set outside the loop
What am I doing wrong in 1. and 2?
——————————————————————
- did not work
for (var i = 1; i <= productCount; i++) { const product = await marketplace.methods.products(i).call() setProducts({ products: [...this.state.products, product] }) }
——————————————————————
- did not work
for (var i = 1; i <= productCount; i++) { const product = await marketplace.methods.products(i).call() setProducts(prevState => ({ products: [...prevState.products, product] })) }
——————————————————————
- worked
let productArray =[] for (var i = 1; i <= productCount; i++) { const product = await marketplace.methods.products(i).call() productArray.push[product] } setProduct(productArray)
——————————————————————
Advertisement
Answer
You’re using a functional component, not a class component, so you shouldn’t be using this
or this.state
– that’s why (1) doesn’t work.
(2) doesn’t work because your initial products are a plain array – it’s not an object with a products
property:
const [products, setProducts] = useState([]);
so
setProducts(prevState => ({ products: [...prevState.products, product] }))
doesn’t make sense – prevState
is an array, not an object with a products
property.
With a small tweak, (2) could be made to work:
setProducts(prevState => ([...prevState, product]));
There’s also almost certainly no need to use .call
, and you can speed up the process by using Promise.all
instead of waiting for each function to finish individually:
Promise.all( Array.from( { length: productCount }, (_, i) => marketplace.methods.products(i + 1)() ) ) .then((newProducts) => { setProducts([...products, ...newProducts]); }) // .catch(handleErrors);
That’s the version I’d prefer, if your code permits you to make all the requests at once.