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

React费用列表应用问题:新增数据后旧数据消失如何解决?

解决React费用列表旧数据被覆盖的问题

问题核心在于当前的状态存储和列表渲染逻辑:

  • expensesData被初始化为单个值,新数据传入时会直接覆盖旧数据
  • ExpenseList仅渲染单个ExpenseItem,无法展示多条数据

以下是具体修改方案:

1. 更新App.js的状态管理

将expensesData改为数组类型,添加新数据时保留原有数据:

import React, { useState, Fragment } from "react";
import ExpenseAddForm from "./ExpenseAddForm/ExpenseAddform";
import ExpenseList from "./ExpenseList/ExpenseList";

const App = () => {
  // 初始化为空数组存储多条费用数据
  const [expensesData, setExpensesData] = useState([]);
  
  const FormData = (datas) => {
    // 用展开运算符添加新数据,避免直接修改原数组
    setExpensesData(prevExpenses => [...prevExpenses, datas]);
  };

  return (
    <Fragment>
      <div className="new-expense">
        <ExpenseAddForm FormData={FormData} />
      </div>
      <ExpenseList listDatas={expensesData}></ExpenseList>
    </Fragment>
  );
};

export default App;

2. 修改ExpenseList.js遍历渲染多个项

遍历listDatas数组,为每个费用项生成ExpenseItem,添加唯一key属性保证渲染稳定性:

import React from "react";
import ExpenseItem from "./ExpenseItem/ExpenseItem";
import ExpenseDateFilter from "./ExpenseDateFilter/ExpenseDateFilter";
import "./ExpenseList.css";

const ExpenseList = (props) => {
  return (
    <div className="expenses">
      <ExpenseDateFilter />
      {/* 遍历数组渲染所有费用项 */}
      {props.listDatas.map((expense) => (
        <ExpenseItem key={expense.id} expenseInfos={expense} />
      ))}
    </div>
  );
};

export default ExpenseList;

3. 修复ExpenseAddForm的Cancel按钮问题并添加唯一ID

当前两个按钮都是type="submit",点击Cancel会触发表单提交;同时为每条数据添加唯一ID,替代index作为key:

import React, { useState } from "react";
import "./ExpenseAddForm.css";

const ExpenseAddForm = (props) => {
  const [title, setTitle] = useState("");
  const [amount, setAmount] = useState("");
  const [date, setDate] = useState("");

  const titleHandler = (e) => {
    setTitle(e.target.value);
  };
  const amountHandler = (e) => {
    setAmount(e.target.value);
  };
  const dateHandler = (e) => {
    setDate(e.target.value);
  };

  const formSubmitHandler = (event) => {
    event.preventDefault();
    const formData = {
      title: title,
      amount: amount,
      date: date,
      // 生成唯一ID,避免用index作为key的潜在问题
      id: Math.random().toString(36).slice(2)
    };
    props.FormData(formData);
    setTitle("");
    setAmount("");
    setDate("");
  };

  // Cancel按钮清空表单逻辑
  const cancelHandler = () => {
    setTitle("");
    setAmount("");
    setDate("");
  };

  return (
    <form onSubmit={formSubmitHandler}>
      <div className="new-expense__controls">
        <div className="new-expense__control">
          <label>Title</label>
          <input type="text" onChange={titleHandler} value={title} />
        </div>
        <div className="new-expense__control">
          <label>Amount</label>
          <input type="number" onChange={amountHandler} value={amount} />
        </div>
        <div className="new-expense__control">
          <label>Date</label>
          <input type="date" onChange={dateHandler} value={date} />
        </div>
      </div>
      <div className="new-expense__actions">
        {/* 修改为button类型,避免触发表单提交 */}
        <button type="button" onClick={cancelHandler}>Cancel</button>
        <button type="submit">Add Expense</button>
      </div>
    </form>
  );
};

export default ExpenseAddForm;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:55:15