React映射时如何将组件渲染到两个不同div中?
React 优化任务列表渲染:避免重复编写
<Task/>组件 我在React中将对象数组作为state(例如名为todos),用两个div分别存放未完成和已完成任务,映射时使用<Task/>组件。当前代码里重复写了两次<Task/>的映射逻辑,想让代码更简洁,是否可行?
我的初始state:
const [todos, setTodos] = useState([ {id: 1, text: 'Lorem', isComplete: true}, {id: 2, text: 'Ipsum', isComplete: true}, {id: 3, text: 'Test', isComplete: false} ]);
当前的JSX结构(简化版):
return ( <div> <h1>Todos</h1> <p>今日待办:</p> <div id="incomplete"></div> <p>已完成任务:</p> <div id="complete"></div> </div> )
我现在的代码存在重复逻辑,不够简洁:
<div className='tasks'> <h2>Tasks</h2> <div className="tasks-incomplete"> <h3>待完成任务</h3> {incompleteTasks.length > 0 && incompleteTasks.map(task => ( <Task key={task.id} id={task.id} text={task.text} isComplete={task.isComplete} dateStart={task.dateStart} dateComplete={task.dateComplete} handleDeleteTask={() => handleDeleteTask(task.id)} handleClickEdit={()=>handleClickEdit(task.id, task.text)} handleComplete={()=>handleComplete(task.id)} /> ))} {incompleteTasks.length === 0 && <p>暂无任务</p>} </div> {completeTasks.length > 0 && ( <div id="completed" className="tasks-complete"> <h3>已完成任务</h3> {completeTasks.map( task => ( <Task key={task.id} id={task.id} text={task.text} isComplete={task.isComplete} dateStart={task.dateStart} dateComplete={task.dateComplete} handleDeleteTask={()=>handleDeleteTask(task.id)} handleClickEdit={()=>handleClickEdit(task.id, task.text)} handleComplete={()=>handleComplete(task.id)} /> ))} </div> )} </div>
优化方案:提取重复逻辑,减少代码冗余
1. 缓存拆分后的任务数组
先用useMemo缓存拆分后的任务数组,避免每次渲染重复计算:
import { useMemo } from 'react'; // ... const incompleteTasks = useMemo(() => todos.filter(task => !task.isComplete), [todos]); const completeTasks = useMemo(() => todos.filter(task => task.isComplete), [todos]);
2. 提取任务列表渲染函数
把重复的<Task/>映射逻辑抽成独立函数,接收任务数组作为参数:
const renderTaskList = (tasks) => { return tasks.map(task => ( <Task key={task.id} {...task} // 解构task对象,自动传入所有属性 handleDeleteTask={() => handleDeleteTask(task.id)} handleClickEdit={() => handleClickEdit(task.id, task.text)} handleComplete={() => handleComplete(task.id)} /> )); };
3. 重构JSX代码
在JSX中直接调用上述函数,替换重复的映射逻辑:
return ( <div className='tasks'> <h2>Tasks</h2> <div className="tasks-incomplete"> <h3>待完成任务</h3> {incompleteTasks.length > 0 ? renderTaskList(incompleteTasks) : <p>暂无任务</p>} </div> {completeTasks.length > 0 && ( <div id="completed" className="tasks-complete"> <h3>已完成任务</h3> {renderTaskList(completeTasks)} </div> )} </div> );
4. 可选:封装任务列表组件(进一步复用)
如果这种任务分组的结构需要多次复用,可以封装成独立组件:
const TaskSection = ({ title, tasks, emptyText, handleDeleteTask, handleClickEdit, handleComplete }) => { if (tasks.length === 0) { return emptyText ? <div>{emptyText}</div> : null; } return ( <div className={`tasks-${title === '待完成任务' ? 'incomplete' : 'complete'}`}> <h3>{title}</h3> {tasks.map(task => ( <Task key={task.id} {...task} handleDeleteTask={() => handleDeleteTask(task.id)} handleClickEdit={() => handleClickEdit(task.id, task.text)} handleComplete={() => handleComplete(task.id)} /> ))} </div> ); };
主组件中使用:
return ( <div className='tasks'> <h2>Tasks</h2> <TaskSection title="待完成任务" tasks={incompleteTasks} emptyText={<p>暂无任务</p>} handleDeleteTask={handleDeleteTask} handleClickEdit={handleClickEdit} handleComplete={handleComplete} /> <TaskSection title="已完成任务" tasks={completeTasks} handleDeleteTask={handleDeleteTask} handleClickEdit={handleClickEdit} handleComplete={handleComplete} /> </div> );
内容的提问来源于stack exchange,提问作者Łukasz Ro
相关产品推荐
相关产品推荐

