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

Next.js中如何精准更新数组指定索引而非全部索引?

问题修复方案

核心问题分析

  • 对象引用复用:初始化时tempReadMoreData定义在forEach循环外部,每次循环仅修改该对象属性后推入数组,导致readMoreState中所有元素指向同一个对象引用,修改任意索引的状态都会同步影响其他索引。
  • 数组元素引用重复:使用Array.fill()填充数组时,所有位置的元素都是同一个对象的引用,后续修改某一索引元素时,其他位置元素也会被动改变。

1. 修复初始化逻辑(useEffect部分)

将tempReadMoreData的定义移至forEach循环内部,确保每个package对应独立对象;同时用Array.from()替代Array.fill(),保证数组内每个元素都是独立对象:

const [readMoreState, setReadMoreState] = useState<readMoreStateAttributes[]>([]);

useEffect(()=>{
    const tempReadMoreArray: readMoreStateAttributes[] = [];
   
    temporaryPackageData?.forEach((packageList, packageIndex)=>{
        // 每次循环创建新对象,避免跨package引用复用
        const tempReadMoreData:readMoreStateAttributes  = {
            textReadMore: [],
            plainReadMore: [],
            checkBoxReadMore:[],
            multipleReadMore:[],
            fileReadMore:[],
            dateReadMore:[]
        };

        const questionCount = packageList?.questions?.length || 0;
        
        // 用Array.from生成独立对象,避免fill导致的引用重复
        tempReadMoreData.plainReadMore = Array.from({length: questionCount}, () => ({
            questionType: 'Plain' as questionTypeAttributes, 
            selectedIndex: null
        }));
        tempReadMoreData.textReadMore = Array.from({length: questionCount}, () => ({
            questionType: 'Text' as questionTypeAttributes, 
            selectedIndex: null
        }));
        tempReadMoreData.checkBoxReadMore = Array.from({length: questionCount}, () => ({
            questionType: 'Checkbox' as questionTypeAttributes, 
            selectedIndex: null
        }));
        tempReadMoreData.dateReadMore = Array.from({length: questionCount}, () => ({
            questionType: 'Date' as questionTypeAttributes, 
            selectedIndex: null
        }));
        tempReadMoreData.fileReadMore = Array.from({length: questionCount}, () => ({
            questionType: 'File' as questionTypeAttributes, 
            selectedIndex: null
        }));
        tempReadMoreData.multipleReadMore = Array.from({length: questionCount}, () => ({
            questionType: 'Multiple choice' as questionTypeAttributes, 
            selectedIndex: null
        }));

        tempReadMoreArray.push(tempReadMoreData);
    });
    setReadMoreState(tempReadMoreArray);
}, [temporaryPackageData?.length])

2. 修复状态更新函数(handleReadMoreFunc)

移除不必要的遍历,精准定位目标package,通过层级拷贝确保仅修改目标索引的状态:

const handleReadMoreFunc = (params: {
    questionEvent: questionTypeAttributes, 
    packageIndex: number, 
    questionIndex: null | number, 
    readMoreAction: 'Read More' | 'Read Less', 
    targetIndex?: number
})=>{
    const {questionEvent, packageIndex, questionIndex, readMoreAction} = params;
    if (questionIndex === null) return;

    // 仅拷贝并修改目标package,其他package保持原引用
    const result = readMoreState.map((item, idx) => {
        if (idx !== packageIndex) return item;

        // 拷贝目标package对象及对应类型数组,避免引用修改
        const updatedPackage = {...item};
        const updatedTextReadMore = [...updatedPackage.textReadMore];
        
        // 更新目标question的状态
        updatedTextReadMore[questionIndex] = {
            questionType: 'Text' as questionTypeAttributes,
            selectedIndex: readMoreAction === 'Read More' ? questionIndex : null
        };

        updatedPackage.textReadMore = updatedTextReadMore;
        return updatedPackage;
    });

    setReadMoreState(result);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:05:36