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

React中如何将表单值存入数组?提交时遇undefined错误

React表单提交添加数组条目报错undefined的解决方案

问题核心原因

  • 直接读取e.target.value错误:<form>元素本身没有value属性,所以e.target.value返回undefined,导致添加到数组的是无效值
  • 未正确收集表单字段:没有获取title、message等输入框的内容,无法生成符合现有数组结构的对象
  • 表单控件缺少必要属性:隐藏输入框和可见输入框都没有name属性,无法被FormData识别;字段名不统一(原数组用messages,表单id是message)

修复方案1:使用FormData快速收集表单数据(轻量便捷)

import { useState } from 'react';

const ForumTopic = [
  {
    title: "First Post",
    messages: "test",
    author: "Dagger",
    count: 1,
    date: "02/16",
  },
];

function TopicManager() {
  const [topic, setTopic] = useState(ForumTopic);

  const addTopic = (e) => {
    e.preventDefault();
    // 用FormData一次性获取所有表单字段
    const formData = new FormData(e.target);
    // 生成符合数组结构的新对象
    const newTopic = {
      title: formData.get('title'),
      messages: formData.get('message'), // 统一字段名:message -> messages
      author: formData.get('author'),
      count: parseInt(formData.get('count')), // 转换为数字类型
      date: formData.get('date').slice(0, 5) // 匹配原数组的MM/DD格式
    };
    // 用函数式更新避免闭包导致的旧state问题
    setTopic(prevTopics => [...prevTopics, newTopic]);
    // 重置表单
    e.target.reset();
  };

  return (
    <div>
      {/* 渲染现有话题列表 */}
      <div className="topic-list">
        {topic.map((item, idx) => (
          <div key={idx} className="topic-item">
            <h3>{item.title}</h3>
            <p>{item.messages}</p>
            <p>作者:{item.author} | 回复数:{item.count} | 日期:{item.date}</p>
          </div>
        ))}
      </div>

      <form onSubmit={addTopic}>
        <div>
          Create a topic title
          <label htmlFor="title">
            <input id="title" name="title" required /> {/* 必须加name属性 */}
          </label>
        </div>
        <div>
          Write your message
          <label htmlFor="message">
            <textarea id="message" name="message" required></textarea> {/* 必须加name属性 */}
          </label>
        </div>
        {/* 隐藏输入框也要加name,FormData才能获取值 */}
        <input id="author" name="author" defaultValue="Dagger" hidden />
        <input id="count" name="count" defaultValue="1" hidden />
        <input id="date" name="date" defaultValue={new Date().toLocaleDateString()} hidden />
        <button type="submit">Post New Message</button>
      </form>
    </div>
  );
}

export default TopicManager;

修复方案2:使用受控组件(符合React数据流习惯)

import { useState } from 'react';

const ForumTopic = [
  {
    title: "First Post",
    messages: "test",
    author: "Dagger",
    count: 1,
    date: "02/16",
  },
];

function TopicManager() {
  const [topic, setTopic] = useState(ForumTopic);
  // 受控组件状态,统一管理表单数据
  const [formState, setFormState] = useState({
    title: '',
    message: '',
    author: 'Dagger',
    count: 1,
    date: new Date().toLocaleDateString().slice(0,5)
  });

  // 统一处理输入变化
  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setFormState(prev => ({
      ...prev,
      [name]: name === 'count' ? parseInt(value) : value
    }));
  };

  const addTopic = (e) => {
    e.preventDefault();
    // 转换为数组需要的结构
    const newTopic = {
      ...formState,
      messages: formState.message
    };
    // 函数式更新state
    setTopic(prevTopics => [...prevTopics, newTopic]);
    // 重置表单状态
    setFormState({
      title: '',
      message: '',
      author: 'Dagger',
      count: 1,
      date: new Date().toLocaleDateString().slice(0,5)
    });
  };

  return (
    <div>
      <div className="topic-list">
        {topic.map((item, idx) => (
          <div key={idx} className="topic-item">
            <h3>{item.title}</h3>
            <p>{item.messages}</p>
            <p>作者:{item.author} | 回复数:{item.count} | 日期:{item.date}</p>
          </div>
        ))}
      </div>

      <form onSubmit={addTopic}>
        <div>
          Create a topic title
          <label htmlFor="title">
            <input 
              id="title" 
              name="title" 
              value={formState.title}
              onChange={handleInputChange}
              required 
            />
          </label>
        </div>
        <div>
          Write your message
          <label htmlFor="message">
            <textarea 
              id="message" 
              name="message" 
              value={formState.message}
              onChange={handleInputChange}
              required
            ></textarea>
          </label>
        </div>
        {/* 受控组件不需要隐藏输入框,直接用state值即可 */}
        <button type="submit">Post New Message</button>
      </form>
    </div>
  );
}

export default TopicManager;

关键修复点总结

  • 移除e.target.value:表单元素无value属性,改用FormData或受控组件收集字段
  • 给所有表单控件加name属性:FormData和受控组件都依赖name来关联数据
  • 统一字段名:原数组用messages,表单输入框对应调整(或转换)
  • 函数式更新state:setTopic(prev => [...prev, newItem])避免闭包导致的旧state问题
  • 类型转换:count是数字类型,需将表单字符串转为数字
  • 日期格式匹配:原数组是MM/DD格式,截取日期字符串对应部分

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:01:51