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

React中如何将已完成Todo移至列表末尾,取消完成时恢复原位置?

React Todo 任务排序解决方案

要实现「标记完成移至底部、取消完成恢复原位置」的功能,核心是给每个任务记录原始创建顺序,渲染时按「未完成任务按原始顺序排列 + 已完成任务按原始顺序排列」的规则组合列表。

1. 完善App组件的状态与逻辑

先修正你App组件里的拼写错误(Headers→Header),并添加状态管理和核心处理函数:

import './App.css';
import Header from './components/Header';
import Form from './components/Form';
import List from './components/List';
import { useState } from 'react';

function App() {
  // 每个todo包含:唯一id、任务文本、完成状态、原始创建顺序
  const [todos, setTodos] = useState([]);
  let nextOrder = todos.length + 1;

  // 添加新任务
  const addTodo = (text) => {
    setTodos([
      ...todos,
      {
        id: Date.now(),
        text,
        done: false,
        order: nextOrder++
      }
    ]);
  };

  // 切换任务完成状态
  const toggleTodo = (id) => {
    setTodos(todos.map(todo => 
      todo.id === id ? {...todo, done: !todo.done} : todo
    ));
  };

  // 排序逻辑:未完成任务按原始顺序排,已完成任务按原始顺序排并放在后面
  const sortedTodos = [
    ...todos.filter(todo => !todo.done).sort((a, b) => a.order - b.order),
    ...todos.filter(todo => todo.done).sort((a, b) => a.order - b.order)
  ];

  return (
    <div className="Todo App">
      <Header />
      <Form addTodo={addTodo} />
      <List todos={sortedTodos} toggleTodo={toggleTodo} />
    </div>
  );
}

export default App;

2. 实现List组件(渲染任务列表)

在./components/List.jsx里编写列表渲染逻辑,接收排序后的todos和切换状态的函数:

const List = ({ todos, toggleTodo }) => {
  return (
    <ul className="todo-list">
      {todos.map(todo => (
        <li 
          key={todo.id}
          className={todo.done ? 'todo-item done' : 'todo-item'}
          onClick={() => toggleTodo(todo.id)}
        >
          {todo.text}
        </li>
      ))}
    </ul>
  );
};

export default List;

3. 简单实现Form组件(添加任务)

在./components/Form.jsx里实现添加任务的表单:

import { useState } from 'react';

const Form = ({ addTodo }) => {
  const [inputText, setInputText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (inputText.trim()) {
      addTodo(inputText.trim());
      setInputText('');
    }
  };

  return (
    <form onSubmit={handleSubmit} className="todo-form">
      <input
        type="text"
        value={inputText}
        onChange={(e) => setInputText(e.target.value)}
        placeholder="添加新任务..."
      />
      <button type="submit">添加</button>
    </form>
  );
};

export default Form;

4. 样式辅助(可选)

在App.css里添加简单样式区分完成状态:

.todo-item {
  padding: 8px;
  margin: 4px 0;
  border: 1px solid #eee;
  cursor: pointer;
}

.todo-item.done {
  text-decoration: line-through;
  color: #999;
}

核心原理说明

  • 每个任务的order属性记录了它被创建的先后顺序,不会随完成状态改变
  • 渲染时先筛选出未完成任务,按order升序排列(保持原始顺序);再筛选已完成任务,同样按order升序排列(保持它们完成前的顺序),最后把两组拼在一起,就实现了「完成任务移到底部,取消完成回到原位置」的效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:40:30