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.