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

React待办列表应用问题:完成项重复及复选框显示异常

解决React待办列表的重复项和已完成项显示复选框问题

嘿,我看你遇到了两个典型的待办列表小问题,咱们一步步来把它们搞定:

问题1:点击完成后出现重复项

现在你的handleComplete方法是把整个活跃任务数组加上当前任务塞进已完成列表里,而且完全没从活跃列表里移除已完成的任务——这就导致活跃列表还留着原项,已完成列表又多塞了整个活跃数组,自然就出现重复了。

修复思路:

  • 在标记任务完成时,需要做两件事:
    1. 从活跃任务数组里移除这个已完成的任务
    2. 把这个任务单独添加到已完成任务数组中

问题2:已完成组件仍显示复选框

你现在的Completed组件直接复用了带复选框的Todo组件,这显然不符合需求——已完成的任务应该是只读展示的,不需要再显示复选框。

修复思路:

  • 修改现有的Todo组件,通过props参数控制是否显示复选框,这样活跃列表用带复选框的版本,已完成列表用隐藏复选框的版本

修改后的完整代码(标注关键修改点)

App.js(核心修改:重构handleComplete方法)

import React from 'react';
import Active from './Components/Active';
import Completed from './Components/Completed';
import Todoform from './Components/Todoform';
import './App.css';

class App extends React.Component {
  state = { items: [], task: '', id: 0, completedItems: [] }

  handleInput = (event) => { 
    this.setState({ task: event.target.value }) 
  }

  handleSubmit = (event) => {
    event.preventDefault()
    const newTask = { id: this.state.id, title: this.state.task }
    const updatedItems = [...this.state.items, newTask]
    this.setState({ items: updatedItems, task: '', id: this.state.id + 1 })
  }

  // 🔧 重构后的完成逻辑:移除活跃项,添加到已完成列表
  handleComplete = (taskId) => {
    // 找到要标记完成的任务
    const completedTask = this.state.items.find(item => item.id === taskId);
    // 过滤掉已完成的任务,更新活跃列表
    const updatedActiveItems = this.state.items.filter(item => item.id !== taskId);
    // 更新状态(用prevState保证状态更新的准确性)
    this.setState(prevState => ({
      items: updatedActiveItems,
      completedItems: [...prevState.completedItems, completedTask]
    }));
  }

  render() {
    return (
      <div id="main-content">
        <h1>Task Lister</h1>
        <Todoform handleChange={this.handleInput} handleSubmit={this.handleSubmit} task={this.state.task} />
        <Active items={this.state.items} handleComplete={this.handleComplete} />
        <Completed completedItems={this.state.completedItems} />
      </div>
    )
  }
}

export default App;

Todo.js(核心修改:支持控制复选框显示,传递任务ID)

import React from 'react'

class Todo extends React.Component{
  state = { checked: false }

  handleCheck = () => { 
    this.setState({ checked: !this.state.checked });
    // 🔧 传递任务ID而非标题,避免同标题任务的识别问题
    this.props.handlecompletedList(this.props.id);
  }

  render(){
    const { title, showCheckbox = true } = this.props; // 默认显示复选框

    return (
      <div className="ui checked checkbox">
        {/* 🔧 根据props决定是否渲染复选框 */}
        {showCheckbox && (
          <input 
            type="checkbox" 
            checked={this.state.checked} 
            onChange={this.handleCheck}
          />
        )}
        <label>{showCheckbox ? `Active: ${title}` : `Completed: ${title}`}</label>
      </div>
    )
  }
}

export default Todo;

Active.js(核心修改:传递任务ID给Todo组件)

import React from 'react'
import Todo from './Todo'

const Active = (props) => {
  const { items, handleComplete } = props

  return(
    <div id="activeList">
      <h2 className="position">Active</h2>
      <ul id="tasks">
        { items.map(item => { 
          return( 
            <Todo 
              key={item.id} 
              id={item.id} // 🔧 新增传递任务ID属性
              handlecompletedList={handleComplete} 
              title={item.title}
            /> 
          ) 
        }) }
      </ul>
    </div>
  )
}

export default Active;

Completed.js(核心修改:传递隐藏复选框的参数)

import React from 'react'
import Todo from './Todo'

const Completed = (props) => {
  const { completedItems } = props

  return(
    <div id="completedList">
      <h2 className="position">Completed</h2>
      <ul id="tasks">
        { completedItems.map(item => { 
          return( 
            <Todo 
              key={item.id} 
              title={item.title}
              showCheckbox={false} // 🔧 隐藏复选框
            /> 
          ) 
        }) }
      </ul>
    </div>
  )
}

export default Completed

Todoform.js(无修改,保持原样)

import React from 'react';

class Todoform extends React.Component {
  render(){
    const {task, handleChange, handleSubmit} = this.props;
    return(
      <form onSubmit={handleSubmit}>
        <label>Task description:</label>
        <input type="text" name="name" placeholder="description" value={task} onChange={handleChange}/>
        <button>Create New Task</button>
      </form>
    )
  }
}

export default Todoform;

这样修改后,两个问题就都解决了:

  • 点击完成复选框后,任务会从活跃列表移除,只出现在已完成列表里,不会出现重复项
  • 已完成列表里的任务不再显示复选框,仅展示已完成的任务文本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:47:38