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

React报错:Cannot set properties of undefined (setting 'full_name')原因咨询

React项目Uncaught TypeError报错分析与解决

问题详情

  • 报错:Uncaught TypeError: Cannot set properties of undefined (setting 'full_name'),触发位置为handleSubmit函数内的obj.full_name = name;行
  • 疑问:该行报错后,后续的obj.email = email;等赋值操作为何未触发同类错误

相关代码

import React, { useState, useEffect } from "react";
import JSONDATA from "../data/MOCK_DATA.json";
import { useNavigate } from "react-router-dom";

const Edit = () => {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [role, setRole] = useState("");
  const [location, setLocation] = useState("");
  const [id, setId] = useState("");

  let navigate = useNavigate();

  var index = JSONDATA.map((e) => {
    return e.id;
  }).indexOf(id);

  const handleSubmit = (e) => {
    e.preventDefault();

    let obj = JSONDATA[index];

    obj.full_name = name;
    obj.email = email;
    obj.role = role;
    obj.location = location;

    navigate("/");
  };

  useEffect(() => {
    setId(localStorage.getItem("id"));
    setName(localStorage.getItem("name"));
    setEmail(localStorage.getItem("email"));
    setRole(localStorage.getItem("role"));
    setLocation(localStorage.getItem("location"));
  }, []);

  return (
    <div className="w-full h-[45rem] max-w-[1500px] mx-auto">
      <h1 className="flex justify-center items-center text-3xl pt-[7rem] font-semibold text-orange-600 mx-auto">
        Edit a new listing
      </h1>
      <form
        className="gap-10 flex h-full flex-col mx-auto justify-center items-center"
        onSubmit={handleSubmit}
      >
        <input
          className=" bg-gray-200 my-2 px-4 rounded-2xl shadow-xl"
          placeholder="Full Name"
          type="text"
          id="name"
          name="name"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />

        <input
          className=" bg-gray-200 my-2 px-4 rounded-2xl shadow-xl"
          placeholder="Email"
          type="email"
          id="email"
          name="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />

        <input
          className=" bg-gray-200 my-2 px-4 rounded-2xl shadow-xl"
          placeholder="Role"
          type="text"
          id="role"
          name="role"
          value={role}
          onChange={(e) => setRole(e.target.value)}
        />

        <input
          className=" bg-gray-200 my-2 px-4 rounded-2xl shadow-xl"
          placeholder="Location"
          type="text"
          id="location"
          name="location"
          value={location}
          onChange={(e) => setLocation(e.target.value)}
        />

        <button
          className="my-2 px-4 py-3 bg-blue-300 active:bg-blue-500 rounded-2xl shadow-xl"
          type="submit"
          onSubmit={handleSubmit}
        >
          Update
        </button>
      </form>
    </div>
  );
};

export default Edit;

问题原因

  1. 代码执行中断:JavaScript是单线程执行模式,当运行到obj.full_name = name;时,发现obj为undefined会立即抛出错误并终止函数执行,后续赋值语句根本不会运行,因此不会触发同类报错。
  2. obj为undefined的根源:
    • 组件初始化时id的初始值是空字符串"",此时计算index会得到-1(JSONDATA中无id为空的项)。
    • 虽然useEffect会从localStorage获取id并更新id状态,但组件初始化时计算的index不会自动更新,导致JSONDATA[index]即JSONDATA[-1]返回undefined。

解决方案

方案1:在handleSubmit内实时计算index

确保每次提交时使用最新的id值获取正确索引:

const handleSubmit = (e) => {
  e.preventDefault();
  // 实时计算索引
  const index = JSONDATA.map(e => e.id).indexOf(id);
  // 处理找不到对应数据的情况
  if (index === -1) {
    console.error("未找到对应ID的数据");
    return;
  }
  let obj = JSONDATA[index];
  obj.full_name = name;
  obj.email = email;
  obj.role = role;
  obj.location = location;
  navigate("/");
};

方案2:用useMemo监听id变化自动更新index

借助useMemo实现index随id状态自动更新:

import React, { useState, useEffect, useMemo } from "react";
// ...其他导入

const Edit = () => {
  // ...状态定义

  // 监听id变化,自动更新index
  const index = useMemo(() => {
    return JSONDATA.map(e => e.id).indexOf(id);
  }, [id]);

  // ...handleSubmit函数
};

额外优化:类型转换与边界处理

如果JSONDATA中的id是数字类型,而localStorage获取的是字符串,需要转换类型后再查找:

const index = JSONDATA.map(e => e.id).indexOf(Number(id));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 20:05:17