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

ReactJS:点击按钮后创建li元素的实现问题求助

问题分析与修复方案

原代码核心问题:

  • 变量/函数名拼写错误:firtValue、hadnleChane、hadnleChan这类错误导致状态无法正确更新
  • 缺少列表数据维护:仅保存单个输入值,无法存储多条支出记录
  • 点击按钮逻辑无效:handleClick仅调用生成单个li的函数,但未更新组件状态触发渲染
  • 列表渲染方式错误:{listOfLi}是引用函数而非调用,无法生成页面元素

修正后的完整代码:

import { useState } from 'react';
import './App.css';

function App() {
  const [income, setIncome] = useState(0);
  const expense = 10;
  const balance = income - expense;
  // 修正拼写错误,维护单个输入框值
  const [firstValue, setFirstValue] = useState("");
  const [secValue, setSecValue] = useState("");
  // 新增状态存储所有支出项
  const [expenseItems, setExpenseItems] = useState([]);

  // 修正函数名拼写,绑定对应输入框状态
  const handleSecondChange = event => {
    setSecValue(event.target.value);
  };

  const handleFirstChange = event => {
    setFirstValue(event.target.value);
  };

  function handleChange(event) {
    setIncome(event.target.value);
  }

  function maxLengthCheck(object) {
    if (object.target.value.length > object.target.maxLength) {
      object.target.value = object.target.value.slice(0, object.target.maxLength);
    }
  }

  function handleClick() {
    // 验证输入不为空后添加到列表
    if (firstValue && secValue) {
      setExpenseItems(prevItems => [
        ...prevItems,
        { item: firstValue, amount: secValue }
      ]);
      // 添加完成后清空输入框
      setFirstValue("");
      setSecValue("");
    }
  }

  return (
    <div>
      <header>
        <div className='App'>
          Expense Tracker
        </div>
      </header>

      <main className='main'>
        <div className='income-box'>
          <div className='income'>Income
            <div className='numbers'>
              {income + "$"}
            </div>
          </div>

          <div className='expense'>Expense
            <div className='numbers'>
              {expense + "$"}
            </div>
          </div>
        </div>

        <div className='income-input'>
          <input 
            type="number" 
            min="0" 
            maxLength="8" 
            onInput={maxLengthCheck} 
            className='input' 
            placeholder='Enter your Income' 
            onChange={handleChange}
          />
        </div>

        <div className='total-balance'>
          Total Balance : {balance}$
        </div>

        <div className='add-item'>Item
          <input 
            type="text" 
            className='adding-input' 
            placeholder='Add Item' 
            onChange={handleFirstChange} 
            value={firstValue}
          />
        </div>

        <div className='add-item'>Amount
          <input 
            type="number" 
            className='adding-input' 
            placeholder='Add Amount' 
            onChange={handleSecondChange} 
            value={secValue}
          />
        </div>

        <div className='add-button'>
          <button type="button" className='expense-button' onClick={handleClick}>Add Expense</button>
        </div>

        <div>
          <ul>
            {/* 遍历支出项生成li元素,添加唯一key */}
            {expenseItems.map((item, index) => (
              <li key={index}>
                {item.item} - {item.amount}$
              </li>
            ))}
          </ul>
        </div>
      </main>
    </div>
  );
}

export default App;

关键改动说明:

  • 修正所有拼写错误,确保状态更新逻辑正常
  • 新增expenseItems数组状态,用于存储所有添加的支出记录
  • 调整handleClick逻辑:验证输入合法性后,将新记录追加到数组,并清空输入框
  • 列表部分通过map遍历数组生成li元素,为每个li添加唯一key属性(实际项目建议使用业务唯一ID替代索引)
  • 给输入框添加value属性,实现受控组件,确保输入值与状态同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 07:10:35