React中默认产品有效期手动更新失效的修复方案咨询
修复React中默认产品有效期手动修改失效问题
问题根源
原代码中的useEffect监听所有productList的变化,包括手动修改默认产品的操作。每次修改后,useEffect都会重新计算其他产品的最长有效期,并强制覆盖默认产品的有效期,导致手动设置的2050被立刻改回。
解决思路
- 增加一个状态标记手动修改默认产品的操作,在手动修改时跳过自动同步逻辑
- 自动同步逻辑仅在非手动操作时执行,并且仅当默认产品的有效期小于其他产品的最长有效期时才更新,保留手动设置的更长值
- 修复状态更新时的直接突变问题(原代码直接修改
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
相关产品推荐
相关产品推荐

