简体   繁体   English

何时在 React 中使用 setState 钩子

[英]When to use setState hook in React

I have a component where I load a list of products with their information.我有一个组件,可以在其中加载包含产品信息的产品列表。

  useEffect(() => {
    getProducts().then((products) => {
      if (products) {
        setLoaded(true);
        setProducts([...products]);
      }
    });
  }, []);

Then inside the render, I go over the products array and calculate the products' total.然后在渲染中,我在产品数组上 go 并计算产品的总数。 Total is also a state within the component. Total 也是组件内的 state。

 {products.length >= 0 &&
              products.map((product) => {
                total += itemQuantity[product.id]
                  ? itemQuantity[product.id] * product.price
                  : 0;
                return (
                  <Product
                    key={product.id}
                    id={product.id}
                    name={product.name}
                    availableCount={product.availableCount}
                    price={product.price}
                    orderedQuantity={
                      itemQuantity[product.id] ? itemQuantity[product.id] : 0
                    }
                    total={
                      itemQuantity[product.id]
                        ? itemQuantity[product.id] * product.price
                        : 0.0
                    }
                    increace={increaseProductuantity}
                    decrease={decreaseProductuantity}
                  />
                );
              })} 

As you can see, in the first line of the map function, I'm adding the price*quantity of each iterated product to the total.如您所见,在 map function 的第一行中,我将每个迭代产品的价格*数量添加到总数中。

Now if I use SetTotal here, it will cause an infinite loop because the product gets rendered every time and every time the total changes.现在,如果我在这里使用 SetTotal,它将导致无限循环,因为每次都会渲染产品并且每次总更改时都会渲染。 so I changed the total directly.所以我直接改变了总数。 and then displayed it like this:然后像这样显示它:

<p>Total: $ {total > 1000 ? 0.9 * total : total} </p>

Is this pattern correct usage of the total state or do I must have to use the setState hook every time I update the state?这种模式是否正确使用了总 state 还是每次更新 state 时都必须使用 setState 挂钩? I just want to utilize the iteration for each product to calculate the total.我只想利用每个产品的迭代来计算总数。 If there is an efficient way of achieving this please share.如果有实现此目标的有效方法,请分享。

Btw here is the full component code:顺便说一句,这里是完整的组件代码:

const Checkout = () => {
  const [loaded, setLoaded] = useState(false);
  const [products, setProducts] = useState([]);
  const [itemQuantity, setItemQuantity] = useState([]);
  let [total, setTotal] = useState(0);

  useEffect(() => {
    getProducts().then((products) => {
      if (products) {
        setLoaded(true);
        setProducts([...products]);
      }
    });
  }, []);

  const increaseProductuantity = (productID) => {
    let quantit = itemQuantity[productID];
 
    quantit
      ? setItemQuantity({ ...itemQuantity, [productID]: ++quantit })
      : setItemQuantity({ ...itemQuantity, [productID]: 1 });
  };
  const decreaseProductuantity = (productID) => {
    let quantit = itemQuantity[productID];
    if (quantit) setItemQuantity({ ...itemQuantity, [productID]: --quantit });
  };

  return (
    <div>
      <header className={styles.header}>
        <h1>Electro World</h1>
      </header>
      <main>
        {!loaded && <LoadingIcon />}
        <table className={styles.table}>
          <thead>
            <tr>
              <th>Product ID</th>
              <th>Product Name</th>
              <th># Available</th>
              <th>Price</th>
              <th>Quantity</th>
              <th>Total</th>
              <th></th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {products.length >= 0 &&
              products.map((product) => {
                total += itemQuantity[product.id]
                  ? itemQuantity[product.id] * product.price
                  : 0;
                return (
                  <Product
                    key={product.id}
                    id={product.id}
                    name={product.name}
                    availableCount={product.availableCount}
                    price={product.price}
                    orderedQuantity={
                      itemQuantity[product.id] ? itemQuantity[product.id] : 0
                    }
                    total={
                      itemQuantity[product.id]
                        ? itemQuantity[product.id] * product.price
                        : 0.0
                    }
                    increace={increaseProductuantity}
                    decrease={decreaseProductuantity}
                  />
                );
              })}
          </tbody>
        </table>
        <h2>Order summary</h2>
        {total > 1000 ? <p>Discount: $ ${0.1 * total} </p> : ""}
        <p>Total: $ {total > 1000 ? 0.9 * total : total} </p>
      </main>
    </div>
  );
};

First of all, read this https://beta.reactjs.org/learn/choosing-the-state-structure首先,阅读这篇https://beta.reactjs.org/learn/choosing-the-state-structure

Avoid duplication in state.避免 state 中的重复。 When the same data is duplicated between multiple state variables, or within nested objects, it is difficult to keep them in sync.当相同的数据在多个 state 变量之间或嵌套对象中重复时,很难使它们保持同步。 Reduce duplication when you can.尽可能减少重复。

In your example, total and itemQuantity can be inferred and shouldn't be a separate states.在您的示例中,可以推断totalitemQuantity并且不应该是单独的状态。

If calculating this is expensive, use useMemo hook如果计算成本很高,请使用useMemo挂钩

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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