You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中默认产品有效期手动更新失效的修复方案咨询

修复React中默认产品有效期手动修改失效问题

问题根源

原代码中的useEffect监听所有productList的变化,包括手动修改默认产品的操作。每次修改后,useEffect都会重新计算其他产品的最长有效期,并强制覆盖默认产品的有效期,导致手动设置的2050被立刻改回。

解决思路

  1. 增加一个状态标记手动修改默认产品的操作,在手动修改时跳过自动同步逻辑
  2. 自动同步逻辑仅在非手动操作时执行,并且仅当默认产品的有效期小于其他产品的最长有效期时才更新,保留手动设置的更长值
  3. 修复状态更新时的直接突变问题(原代码直接修改pre对象,不符合React状态不可变原则)

修改后关键代码

1. 添加手动操作标记状态

const [isManualEdit, setIsManualEdit] = useState(false);

2. 修改手动编辑函数

const editDefaultProduct = () =>{
  setProductList((pre) => {
    // 深拷贝状态,避免直接修改原对象
    const newProductList = {...pre};
    newProductList["Category_A"] = pre["Category_A"].map(p => ({...p}));
    const defaultProduct = newProductList["Category_A"].find(p => p.productName === "defaultProduct");
    if (defaultProduct) {
      defaultProduct.expiryYear = 2050;
    }
    return newProductList;
  });
  // 标记为手动修改
  setIsManualEdit(true);
}

3. 重构useEffect逻辑

useEffect(() => {
  // 手动修改时跳过自动同步,重置标记
  if (isManualEdit) {
    setIsManualEdit(false);
    return;
  }

  let longestExpiryYear = 0;
  // 计算所有非默认产品的最长有效期
  Object.entries(productList).forEach(([_, products]) => {
    products.forEach((product) => {
      if (product.productName !== "defaultProduct") {
        longestExpiryYear = Math.max(longestExpiryYear, product.expiryYear);
      }
    });
  });

  if (longestExpiryYear) {
    setProductList((pre) => {
      const newProductList = {...pre};
      newProductList["Category_A"] = pre["Category_A"].map(p => ({...p}));
      const defaultProduct = newProductList["Category_A"].find(p => p.productName === "defaultProduct");
      // 仅当默认产品有效期小于最长有效期时更新,保留手动设置的更长值
      if (defaultProduct && defaultProduct.expiryYear < longestExpiryYear) {
        defaultProduct.expiryYear = longestExpiryYear;
      }
      return newProductList;
    });
  }
}, [productList, isManualEdit]);

修改后完整代码

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

export default function App() {
  const productListdemo = {
    Category_A: [{ productName: "defaultProduct", expiryYear: 2020 }],
  };

  const [productList, setProductList] = useState(productListdemo);
  // 新增手动编辑标记
  const [isManualEdit, setIsManualEdit] = useState(false);

  const addFirstProduct = () => {
    const product = {
      Category_B: [{ productName: "sausage", expiryYear: 2030 }],
    };
    setProductList((pre) => {
      return { ...pre, ...product };
    });
  };

  const addSecondProduct = () => {
    const product = {
      Category_B: [
        { productName: "sausage", expiryYear: 2020 },
        { productName: "meat", expiryYear: 2040 },
      ],
    };
    setProductList((pre) => {
      return { ...pre, ...product };
    });
  };

  const editDefaultProduct = () =>{
    setProductList((pre) => {
      const newProductList = {...pre};
      newProductList["Category_A"] = pre["Category_A"].map(p => ({...p}));
      const defaultProduct = newProductList["Category_A"].find(p => p.productName === "defaultProduct");
      if (defaultProduct) {
        defaultProduct.expiryYear = 2050;
      }
      return newProductList;
    });
    setIsManualEdit(true);
  }

  const showProductList = () =>{
    console.log(productList)
  }

  useEffect(() => {
    if (isManualEdit) {
      setIsManualEdit(false);
      return;
    }

    let longestExpiryYear = 0;
    Object.entries(productList).forEach(([_, products]) => {
      products.forEach((product) => {
        if (product.productName !== "defaultProduct") {
          longestExpiryYear = Math.max(longestExpiryYear, product.expiryYear);
        }
      });
    });

    if (longestExpiryYear) {
      setProductList((pre) => {
        const newProductList = {...pre};
        newProductList["Category_A"] = pre["Category_A"].map(p => ({...p}));
        const defaultProduct = newProductList["Category_A"].find(p => p.productName === "defaultProduct");
        if (defaultProduct && defaultProduct.expiryYear < longestExpiryYear) {
          defaultProduct.expiryYear = longestExpiryYear;
        }
        return newProductList;
      });
    }
  }, [productList, isManualEdit]);

  return (
    <div className="App">
      <button onClick={addFirstProduct}>add first product</button>
      <br />
      <button onClick={addSecondProduct}>add second product</button>
      <br />
      <button onClick={editDefaultProduct}>Edit Default Product expiry year to 2050</button>
      <br />
      <button onClick={showProductList}>show product list </button>
    </div>
  );
}

效果验证

  • 场景1:点击「add first product」,默认产品有效期自动同步为2030
  • 场景2:点击「add second product」,默认产品有效期自动更新为2040
  • 场景3:点击「Edit Default Product expiry year to 2050」,默认产品有效期保留2050,不会被改回;后续若添加有效期大于2050的产品,默认产品会自动同步到该值

内容的提问来源于stack exchange,提问作者Ae Leung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:25:25