ReactJS:如何在对象数组中添加对象?分页筛选场景实现
Got it, let's get this working properly for you! I've put together a complete React component that meets all your requirements: grouping items 3 per page, pagination controls, alphabetical filtering, and a working add item feature that correctly integrates with your filtered list.
Complete Working Implementation
Here's the full code with explanations of key improvements:
import React, { Component } from 'react'; class ItemList extends Component { constructor(props) { super(props); this.state = { // 维护原始数据源,filtered列表会基于这个动态生成 originalItems: [ { id: 1, name: "Apple" }, { id: 2, name: "Banana" }, { id: 3, name: "Cherry" }, { id: 4, name: "Date" }, { id: 5, name: "Elderberry" }, ], filterText: "", // 字母筛选的输入值 inputValue: "", // 添加新项的输入值 currentPage: 0, itemsPerPage: 3, }; } // 动态计算过滤后的数组,保证数据一致性 getFilteredItems = () => { const { originalItems, filterText } = this.state; if (!filterText.trim()) return originalItems; // 不区分大小写的前缀匹配,支持首字母或完整名称筛选 return originalItems.filter(item => item.name.toLowerCase().startsWith(filterText.toLowerCase()) ); }; goToPrevPage = () => { this.setState(prev => ({ currentPage: Math.max(prev.currentPage - 1, 0) })); }; goToNextPage = () => { const filteredItems = this.getFilteredItems(); const maxPage = Math.ceil(filteredItems.length / this.state.itemsPerPage) - 1; this.setState(prev => ({ currentPage: Math.min(prev.currentPage + 1, maxPage) })); }; handleFilterChange = (e) => { this.setState({ filterText: e.target.value, currentPage: 0, // 筛选后自动回到第一页 }); }; handleInputChange = (e) => { this.setState({ inputValue: e.target.value }); }; addItem = () => { const { inputValue, originalItems } = this.state; // 空值不添加,避免无效项 if (!inputValue.trim()) return; // 生成唯一ID,避免重复key问题(你原来的固定id:0会导致渲染错误) const newItem = { id: originalItems.length > 0 ? Math.max(...originalItems.map(i => i.id)) + 1 : 1, name: inputValue.trim() }; // 更新原始数组,而不是直接修改filtered,这样筛选状态下新项也会被正确处理 this.setState(prev => ({ originalItems: [...prev.originalItems, newItem], inputValue: "", // 添加后清空输入框 currentPage: 0, // 回到第一页查看新项 })); }; render() { const { currentPage, itemsPerPage, filterText, inputValue } = this.state; const filteredItems = this.getFilteredItems(); // 截取当前页要显示的项 const currentItems = filteredItems.slice( currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage ); const maxPage = Math.ceil(filteredItems.length / itemsPerPage) - 1; return ( <div style={{ padding: "20px", maxWidth: "600px", margin: "0 auto" }}> {/* 字母筛选区域 */} <div style={{ marginBottom: "15px" }}> <label>按字母筛选:</label> <input type="text" value={filterText} onChange={this.handleFilterChange} placeholder="输入首字母或名称" style={{ marginLeft: "10px", padding: "5px" }} /> </div> {/* 添加新项区域 */} <div style={{ marginBottom: "15px" }}> <input type="text" value={inputValue} onChange={this.handleInputChange} placeholder="输入新名称" style={{ padding: "5px" }} /> <button onClick={this.addItem} style={{ marginLeft: "10px", padding: "5px 10px" }}> 添加 </button> </div> {/* 列表显示区域 */} <ul style={{ listStyle: "none", padding: 0 }}> {currentItems.length > 0 ? ( currentItems.map(item => ( <li key={item.id} style={{ padding: "8px", borderBottom: "1px solid #eee" }}> {item.name} </li> )) ) : ( <li style={{ padding: "8px" }}>没有匹配的内容</li> )} </ul> {/* 分页控制区域 */} <div style={{ marginTop: "15px" }}> <button onClick={this.goToPrevPage} disabled={currentPage === 0} style={{ padding: "5px 10px", marginRight: "10px" }} > 上一页 </button> <button onClick={this.goToNextPage} disabled={currentPage >= maxPage} style={{ padding: "5px 10px" }} > 下一页 </button> <span style={{ marginLeft: "15px" }}> 第 {currentPage + 1} 页 / 共 {maxPage + 1} 页 </span> </div> </div> ); } } export default ItemList;
Key Fixes & Improvements Over Your Original Code
- Avoided Direct Filtered Array Modification: Instead of pushing directly to
filtered, we maintain anoriginalItemssource array. The filtered list is computed dynamically based on this source and the current filter text—this ensures data consistency (e.g., new items will automatically respect active filters). - Unique ID Generation: Your original code used a fixed
id: 0which would cause React rendering errors due to duplicate keys. Now we generate a unique ID based on the highest existing ID in the array. - Input Validation: We don't allow empty values to be added to the list.
- Better Pagination Logic: Added disabled states for pagination buttons to prevent invalid page navigation, and show clear page number feedback.
- User Experience Touches: Clears the input field after adding an item, and resets to the first page so users immediately see their new entry.
内容的提问来源于stack exchange,提问作者Jota
相关产品推荐
相关产品推荐

