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

React使用useState给嵌套对象赋值时报Cannot set properties of undefined错误

报错原因

该报错是两个问题共同导致的:

  1. 初始errors状态为空对象{},本身不存在email属性,所以errors.email的取值为undefined,直接尝试给undefined设置primary属性自然会抛出对应错误。
  2. 你的写法直接修改了state原对象,不符合React状态不可变的更新规范,哪怕不报错也可能导致视图无法正常触发更新。
正确实现方案

方案1:原生React手动展开实现(无需额外依赖)

调用setErrors时传入新的状态对象,逐层展开原有属性避免覆盖已有的值,同时补全嵌套的上层结构:

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

export default function App() {
  const [errors, setErrors] = useState({});

  useEffect(() => {
    // 使用函数式更新获取最新的prevErrors状态,避免闭包问题
    setErrors(prevErrors => ({
      ...prevErrors, // 保留errors下除email外的其他已有属性
      email: {
        ...prevErrors.email, // 保留email下除primary外的其他已有属性
        primary: "abc@gmail.com"
      }
    }))
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

方案2:使用immer库简化深层嵌套更新(适合复杂嵌套场景)

如果嵌套层级很深,手动逐层展开很容易出错,可以使用immer库来实现类似直接修改原对象的写法,内部自动生成不可变的新状态:

  1. 先安装依赖:npm install immer use-immer
  2. 替换原有useState为useImmer:
import "./styles.css";
import { useEffect } from "react";
import { useImmer } from "use-immer";

export default function App() {
  const [errors, setErrors] = useImmer({});

  useEffect(() => {
    setErrors(draft => {
      // 这里可以直接修改draft对象,immer会自动生成新的不可变状态
      if (!draft.email) draft.email = {}; // 补全上层结构
      draft.email.primary = "abc@gmail.com";
    })
  }, []);
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:12:02