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

React调用setState后未重新渲染?待办列表删除任务页面不更新

React待办列表删除后页面不更新的问题解决

问题根源

核心问题是状态层级不匹配:任务列表的数据源(tasks)存储在App组件的state中,但删除操作完成后,你在TaskItem组件里调用this.setState({tasks}),这只会更新TaskItem自己的state,并不会影响App组件的state。而页面渲染依赖的是App的state,所以只要App的state没变化,页面就不会自动刷新。

解决方案:通过回调函数传递状态更新逻辑

我们需要把更新App组件state的逻辑,通过props从父组件传递到子组件,让TaskItem在删除成功后触发这个逻辑,从而更新页面。

步骤1:在App组件中封装任务列表更新方法

修改App.js,把获取任务的逻辑封装成独立方法,并传递给TaskList:

import React from 'react';
import taskApi from "../api/task-api";
import TaskList from "./TaskList";
import {Button, Container} from "react-bootstrap";

class App extends React.Component {
    state = {
        tasks: [],
    }

    componentDidMount() {
        this.fetchTasks();
    }

    // 封装获取任务列表的方法
    fetchTasks = () => {
        taskApi.get('/tasks').then(
            res => {
                const tasks = res.data.data;
                this.setState({tasks})
            }
        );
    }

    render() {
        return(
            <Container>
                <h1>Task Manager</h1>
                <Button variant="primary" size="lg" className="add-task-button">Add Task</Button>
                {/* 将fetchTasks方法通过props传递给TaskList */}
                <TaskList tasks={this.state.tasks} fetchTasks={this.fetchTasks} />
            </Container>
        );
    }
}

export default App;

步骤2:在TaskList中传递方法给TaskItem

修改TaskList.js,把fetchTasks方法继续传递给每个TaskItem:

import React from 'react';
import Table from 'react-bootstrap/Table'

import TaskItem from "./TaskItem";

class TaskList extends React.Component {
    render() {
        return(
                <Table striped bordered hover>
                    <thead>
                        <tr key="header">
                            <th>ID #</th>
                            <th>Task Name</th>
                            <th></th>
                        </tr>
                    </thead>
                    <tbody>
                    {this.props.tasks.map((task) => {
                        // 将fetchTasks传递给TaskItem
                        return <TaskItem task={task} key={task.id} fetchTasks={this.props.fetchTasks} />
                    })}
                    </tbody>
                </Table>
        );
    }
}

export default TaskList;

步骤3:在TaskItem中调用父组件的更新方法

修改TaskItem.js的deleteTask方法,删除成功后调用props中的fetchTasks来更新App的state:

import React from 'react';
import {Button, Modal} from "react-bootstrap";
import taskApi from "../api/task-api";


class TaskItem extends React.Component {

    constructor() {
        super();
        this.state = {
            show: false,
        };
    }

    showModal() {
        this.setState({show: true});
    }

    closeModal() {
        this.setState({show: false});
    }

    deleteTask(task_id) {
        this.setState({show: false});
        taskApi.delete('/task/' + task_id).then(()=>{
            // 调用父组件传递的方法,更新App的任务列表
            this.props.fetchTasks();
        });
    }

    render() {
        return(
                <tr>
                    <td>{this.props.task.id}</td>
                    <td>{this.props.task.task_name}</td>
                    <td>
                        <Button variant="success" className="task-action-button">Complete</Button>
                        <Button variant="secondary" className="task-action-button">Edit</Button>
                        <Button variant="danger" className="task-action-button" onClick={()=>{this.showModal()}}>Delete</Button>
                        <Modal show={this.state.show}>
                            <Modal.Header>Confirm</Modal.Header>
                            <Modal.Body>
                                Are you sure you want to delete this task?
                                <br/><br/>
                                <strong>Task:</strong>
                                <br/>
                                {this.props.task.task_name}
                            </Modal.Body>
                            <Modal.Footer>
                                <Button variant="secondary" onClick={()=>{this.closeModal()}}>Cancel</Button>
                                <Button variant="danger" onClick={()=>{this.deleteTask(this.props.task.id)}}>Delete</Button>
                            </Modal.Footer>
                        </Modal>
                    </td>
                </tr>
        );
    }
}

export default TaskItem;

额外优化:减少API请求

上面的方案需要删除后重新请求整个任务列表,其实可以直接在App组件中过滤掉已删除的任务,省去一次API请求:

  1. 在App.js中添加删除任务的方法:
deleteTask = (task_id) => {
    taskApi.delete('/task/' + task_id).then(()=>{
        // 直接过滤state中的任务,无需重新请求API
        this.setState(prevState => ({
            tasks: prevState.tasks.filter(task => task.id !== task_id)
        }));
    });
}
  1. 把deleteTask传递给TaskList,再传递给TaskItem,然后在TaskItem的deleteTask方法中调用this.props.deleteTask(task_id)即可。

这样既减少了网络请求,也能实现页面实时更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:54:36