如何在 React 中动态创建并渲染列表项(li)元素

1次阅读

如何在 React 中动态创建并渲染列表项(li)元素

本文详解如何使用 react 的 usestate hook 管理动态列表状态,通过点击按钮将两个输入框的值组合成新列表项(li),并安全、高效地渲染到 ul 中。涵盖状态设计、事件处理、jsx 渲染及关键注意事项。

本文详解如何使用 react 的 usestate hook 管理动态列表状态,通过点击按钮将两个输入框的值组合成新列表项(li),并安全、高效地渲染到 ul 中。涵盖状态设计、事件处理、jsx 渲染及关键注意事项。

在 React 应用中,动态添加 dom 元素(如

  • )不能像原生 JavaScript 那样直接操作 DOM,而应遵循「状态驱动视图」原则:数据变化 → 状态更新 → 视图自动重渲染。以下是一个完整、可运行的实现方案。

    ✅ 核心思路

    • 使用 useState 维护一个数组状态(如 values),用于存储所有待渲染的列表内容;
    • 输入框通过 onChange 实时更新对应字段(firtValue 和 secValue);
    • 点击按钮时,将二者拼接后追加至 values 数组;
    • 在 JSX 中通过 .map() 将 values 映射为
    • 元素列表,并确保每个 li 拥有唯一 key。

    ✅ 完整代码实现

    import { useState } from 'react';  function App() {   const [income, setIncome] = useState(0);   const expense = 10;   const balance = income - expense;   const [firtValue, setFirtValue] = useState('');   const [secValue, setSecValue] = useState('');   // ✅ 新增:用于存储所有待渲染的 li 文本的数组状态   const [values, setValues] = useState([]);    const hadnleChane = (event) => setSecValue(event.target.value);   const hadnleChan = (event) => setFirtValue(event.target.value);    const handleChange = (event) => setIncome(event.target.value);    const maxLengthCheck = (object) => {     if (object.target.value.length > object.target.maxLength) {       object.target.value = object.target.value.slice(0, object.target.maxLength);     }   };    // ✅ 正确的点击处理:更新状态,触发重渲染   const handleClick = () => {     if (firtValue.trim() && secValue.trim()) {       setValues(prev => [...prev, `${firtValue} — $${secValue}`]);       // 可选:清空输入框       setFirtValue('');       setSecValue('');     }   };    // ✅ 正确渲染:基于 values 数组生成 li 列表   const listOfLi = values.map((value, index) => (     <li key={index}>{value}</li>   ));    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={hadnleChane}           />         </div>          <div className="add-item">           Amount           <input             type="number"             className="adding-input"             placeholder="Add Amount"             onChange={hadnleChan}           />         </div>          <div className="add-button">           <button             type="button"             className="expense-button"             onClick={handleClick}           >             Add Expense           </button>         </div>          <div>           <ul>{listOfLi}</ul>         </div>       </main>     </div>   ); }  export default App;

    ⚠️ 关键注意事项

    • 不要在 onClick 中直接调用 JSX 函数(如原代码中的 listOfLi()):这仅返回一个 React 元素对象,不会影响 DOM,也不会触发渲染。
    • 必须使用 key 属性:.map() 渲染列表时,key 是 React 识别元素身份的必要标识;推荐使用稳定索引(如 index)或更佳的唯一 ID(若数据支持)。
    • 避免直接修改状态数组:始终使用 setValues(prev => […prev, newItem]) 等不可变方式更新,防止状态失效。
    • 增强健壮性:添加空值校验(如 trim() 判断),避免插入空白项;可选地在添加后重置输入框,提升用户体验。
    • 命名规范建议:firtValue 应为 firstValue(原文拼写错误),实际项目中请修正以保障可维护性。

    掌握这一模式后,你可轻松扩展功能——例如支持删除某项(通过 Filter)、编辑、持久化到 localStorage,或升级为受控组件+表单提交等高级场景。

  • text=ZqhQzanResources