用功能组件中的另一个状态更新状态

update state with another state in functional component

我有一个状态,每次当另一个状态时都需要更新 changes.So 我使用了另一个状态的依赖数组项的效果,但它导致了无限渲染。 我想将这些变量用作状态。 我希望 totalAmount 成为一个状态变量,其他变量需要成为状态(折扣小计等)。 有什么解决办法。

App.js

import { useState, useEffect } from 'react';
import './styles.css';

function App() {
  let order = [
    {
      qty: 2,
      name: 'Margarita A',
      variant: 'crab & cucumber',
      price: '412.00',
    }
  ];


  let [discount, setDiscount] = useState(759.5),
    [deliveryFee, setDeliveryFee] = useState(12.0),
    [taxes, setTaxes] = useState(46.15),
    [subtotal, setSubtotal] = useState(0),
    [totalAmount, setTotalAmount] = useState(0);
  useEffect(() => {
    setTotalAmount(subtotal - discount + deliveryFee + taxes);
  }, [subtotal, discount, deliveryFee, taxes]);

  return (
    <div className="app">
      <div className="container">    
          <div className="orderItems">
            {order.map((item, i) => {
              // subtotal += +item.price;
              setSubtotal((prev) => prev + +item.price);

              return (
                <div className="orderItem" key={i}>
                  <span className="orderItemPrice">₹{item.price}</span>
                </div>
              );
            })}
          </div>
        </div>

        <div className="summary">
          <span className="summaryTitle">Summary</span>
          <div className="total amountBox">
            <span>Total</span>
            <span>₹ {totalAmount}</span>
          </div>
        </div>
      </div>
      <div className="placeOrder">
        <button onClick={(e, totalAmount) => {}}>PLACE ORDER</button>
      </div>
    </div>
  );
}

export default App;

问题

问题不在于您的 useEffect 挂钩,它工作正常并在组件挂载时调用一次。问题出在 return 方法中的 setSubtotal((prev) => prev + +item.price);

状态变量的每次更改都会导致重新渲染,每次重新渲染都会重新创建您的 order.map。因此在 order.map 期间更改状态将导致重新渲染,而重新渲染会导致 order.map 再次绘制。这是无限重新渲染的原因。

注意: 您可以简单地在 map 函数中注释 setState 来阻止这种行为。

解决方案

有一些选项可以控制这种情况,例如对 subtotal 使用 useRef 来防止重新渲染的原因。

此外,您可以在计算 totalAmount 和设置它之前在 useEffect 钩子中计算 subtotal

function App() {
  let order = [
    {
      qty: 2,
      name: "Margarita A",
      variant: "crab & cucumber",
      price: "412.00"
    }
  ];

  const [discount, setDiscount] = useState(59.5);
  const [deliveryFee, setDeliveryFee] = useState(12.0);
  const [taxes, setTaxes] = useState(46.15);
  const [subtotal, setSubtotal] = useState(0);
  const [totalAmount, setTotalAmount] = useState(0);

  useEffect(() => {
    const localSubtotal = order.reduce(
      (acc, curr) => (acc += Number(curr.price)),
      0
    );

    setSubtotal(localSubtotal);
    setTotalAmount(localSubtotal - discount + deliveryFee + taxes);
  }, [discount, deliveryFee, taxes, order]);

  return (
    <div className="app">
      <div className="container">
        <div className="orderItems">
          {order.map((item, i) => {
            return (
              <div className="orderItem" key={i}>
                <span className="orderItemPrice">₹{item.price}</span>
              </div>
            );
          })}
        </div>
      </div>

      <div>
        <div className="summary">
          <div>
            <span>Sub Total: {subtotal}</span>
          </div>
          <span className="summaryTitle">Summary</span>
          <div className="total amountBox">
            <span>Total</span>
            <span>₹ {totalAmount}</span>
          </div>
        </div>
      </div>
      <div className="placeOrder">
        <button onClick={(e, totalAmount) => {}}>PLACE ORDER</button>
      </div>
    </div>
  );
}

export default App;

注意:不要忘记在useEffect hook的依赖数组中传递order数组。