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

Redux中dispatch changeStatus action组件未重新渲染,dispatch removeTask action正常的问题排查

Why Your completeTask Action Isn't Triggering Component Re-renders

Hey there! Let's figure out why your component isn't updating when you dispatch the completeTask action, even though removeTask seems to work. I've spotted two key issues in your code that are causing this:


1. You're Mutating the Original Redux State (A Big No-No!)

Redux requires immutable state updates—you can't modify the original state directly. Your current reducer is mutating the existing tasks array instead of creating new copies, which tricks Redux into thinking nothing changed (it uses shallow comparison to detect updates; if the array reference stays the same, it skips re-renders).

Here's what's wrong in your reducer:

  • In addTask, let list = state.tasks creates a reference to the original array, then list.push(...) modifies it directly.
  • In completeTask, you're updating list[index].status on the original array's item without creating a new object.
  • Even removeTask uses list.splice(...), which mutates the original array (the fact that it works sometimes is just a coincidence, not correct behavior).

Fix the Reducer to Use Immutable Updates

Rewrite your reducer to return new arrays/objects every time you make a change:

const HandleTaskReducer = (state = initializeState, action) => {
    switch (action.type) {
        case addTask: {
            // Create a new array with the new task appended
            const newTasks = [...state.tasks, action.payload];
            localStorage.setItem('todos', JSON.stringify(newTasks));
            return { ...state, tasks: newTasks };
        }
        case completeTask: {
            // Map to a new array, and create a new object for the updated task
            const newTasks = state.tasks.map(task => 
                task.id === action.payload 
                    ? { ...task, status: true } 
                    : task
            );
            localStorage.setItem('todos', JSON.stringify(newTasks));
            return { ...state, tasks: newTasks };
        }
        case removeTask: {
            // Filter to create a new array excluding the deleted task
            const newTasks = state.tasks.filter(task => task.id !== action.payload);
            localStorage.setItem('todos', JSON.stringify(newTasks));
            return { ...state, tasks: newTasks };
        }
        default: {
            return state; // No need to spread here if no changes were made
        }
    }
}

2. Your ListTaskComponent is Using Stale Local State

In ListTaskComponent, you're copying the Redux state into a local useState variable, but your useEffect only runs once when the component mounts (thanks to the empty dependency array). When the Redux state updates, your component receives new props, but the local tasks state never gets updated—so you're always rendering the initial list of tasks.

Remove the Local State and Use Props Directly

You don't need local state here—just use the props provided by connect directly:

import React from 'react';
import TaskItemComponent from "./TaskItemComponent";
import {connect} from "react-redux";

const ListTaskComponent = props => {
    // Use the props directly instead of syncing to local state
    const taskList = props.taskState.tasks.map(value => 
        <TaskItemComponent 
            key={value.id.toString()} 
            task={value}
        /> 
    );
    return (
        <section id="wrap-task" className="mt-3">
            {taskList}
        </section>
    )
}

const mapStateToProps = state => {
    return {
        taskState: state.taskReducer,
    }
}

export default connect(mapStateToProps, null)(ListTaskComponent)

Why This Fixes the Problem

  • By returning new arrays/objects in the reducer, Redux can detect the state change and trigger component re-renders correctly.
  • Using props directly in ListTaskComponent ensures you always render the latest data from Redux, no need to manually sync local state.

Give these changes a try—your completeTask action should now trigger a re-render just like removeTask does!

内容的提问来源于stack exchange,提问作者Khả Nam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:27:35