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

React中如何为状态对象内的指定类型数组添加元素?

问题解决:React中给useState对象的数组属性添加元素

先梳理你代码里的核心问题,再给出修正后的实现:

原代码的错误点

  • 参数传递错误:onClick事件里错误地把e作为第一个参数传给addItem,但函数定义里第一个参数是itemType,导致参数顺序完全混乱。
  • 属性访问语法错误:用sort.type.push(...)无法访问到循环变量type对应的属性,必须用方括号语法sort[type]。
  • 直接修改State:React的State是不可变的,不能直接对原state对象的数组执行push操作,必须创建新的数组和对象来更新。
  • for...in循环的hasOwnProperty用法错误:应该是sort.hasOwnProperty(type),而非type.hasOwnProperty(type)。
  • 未触发重新渲染:直接把原sort对象传给setSort,因为对象引用未改变,React不会触发组件重新渲染。

修正后的代码

import { useState, useEffect } from "react";

function Items() {
    const [sort, setSort] = useState({
        "city": [],
        "price": [],
        "year": []
    });

    useEffect(() => {
        console.log(sort);
    }, [sort])

    function addItem(itemType, itemValue) {
        const targetType = itemType.toLowerCase();
        // 用函数式更新确保拿到最新的state值
        setSort(prevSort => {
            // 创建新数组,添加新元素,不修改原数组
            const updatedArray = [...prevSort[targetType], itemValue];
            // 返回新的state对象,保留其他属性不变
            return {
                ...prevSort,
                [targetType]: updatedArray
            };
        });
    }

    return (
        <>
            {/* 移除多余的e参数,传递正确的类型和值 */}
            <div className="item" onClick={() => addItem("City", "Los Angeles")}>
                <span>Add LA</span>
            </div>
            <div className="item" onClick={() => addItem("City", "New York")}>
                <span>Add NY</span>
            </div>
        </>
    )
}

export default Items

关键说明

  • 函数式更新State:当新state依赖旧state时,用setSort(prevSort => ...)能确保获取到最新的state值,避免闭包导致的更新异常。
  • 不可变更新原则:用扩展运算符[...prevSort[targetType], itemValue]创建新数组,用{...prevSort, [targetType]: updatedArray}创建新对象,保证原state不被直接修改,符合React的状态更新规则。
  • 简化逻辑:无需遍历所有属性,直接通过统一小写后的类型名访问对应数组,代码更简洁高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:15:29