简体   繁体   中英

Update state array in React JS with item from Smart Contract

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

  1. 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?

——————————————————————

  1. did not work
  for (var i = 1; i <= productCount; i++) {
        const product = await marketplace.methods.products(i).call()
        setProducts({
          products: [...this.state.products, product]
        })
      }

——————————————————————

  1. did not work
  for (var i = 1; i <= productCount; i++) {
        const product = await marketplace.methods.products(i).call()
         setProducts(prevState => ({
            products: [...prevState.products, product]
         }))
      }

——————————————————————

  1. worked
  let productArray =[]
  for (var i = 1; i <= productCount; i++) {
        const product = await marketplace.methods.products(i).call()
        productArray.push[product]
      }
  setProduct(productArray)

——————————————————————

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.

1 and 2 disobey the one of the basic rules of hooks in React.

Only Call Hooks at the Top Level . ie You should avoid calling hooks in loops, nested functions or conditionals.

As already stated also, there is no reason for the use of this in the first approach considering the fact that you're using a React hook.

Read more about Hooks Rules on the docs .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM