React Redux не обновляет список элементов

Вопрос или проблема

**У меня возникли проблемы с обновлением состояния в React с использованием Redux. Мое состояние – это список объектов, и по какой-то причине оно не обновляется правильно, когда я пытаюсь его изменить. Вместо обновленного списка я продолжаю получать прокси-массив, когда печатаю состояние в консоли. Я не уверен, правильно ли я обрабатываю неизменяемость или что-то упускаю в своем редьюсере. Мог бы кто-нибудь помочь мне разобраться, что идёт не так, или дать рекомендации о том, как правильно обновить состояние, которое является массивом объектов?

**
Это мой TodoSlice

import { createSlice, current, PayloadAction } from "@reduxjs/toolkit";

export interface Todo {
    id: string;
    task: string;
    completed: boolean;
}

export const TOGGLE_COMPLETE = "TOGGLE";
export const UPDATE = "UPDATE";
const initialState: Array<Todo> = [
    {
        id: "1123123",
        task: "Динамические отчеты и панели мониторинга",
        completed: false
    },
    {
        id: "2352352",
        task: "Шаблоны для всех",
        completed: true
    },
    {
        id: "46264624",
        task: "Процесс разработки",
        completed: true
    },
    {
        id: "68576",
        task: "Безграничная бизнес-автоматизация",
        completed: false
    }
];

const todoSlice = createSlice({
    name: "todoSlice",
    initialState,
    reducers: {
        updateTodo: (state, action: PayloadAction<Todo>) => {
            state = [...current(state).map(todo => todo.id === action.payload.id ? { ...action.payload } : todo)];
            console.log(state);
        },
        updateTodoTask: (state, action: PayloadAction<Todo>) => {
            state = state.map(todo => todo.id === action.payload.id ? { ...action.payload } : todo);
        },
        addTodo: (state, action: PayloadAction<{task: string, completed: boolean}>) => {
            const id = Math.max(...state.map(todo => parseInt(todo.id))) + 1;
            const todo: Todo = {id : ""+id, task: action.payload.task, completed: action.payload.completed};
            state.push(todo);
        },
        deleteTodo: (state, action: PayloadAction<Todo>) => {
            console.log(action.payload)
            state = state.filter(todo => todo.id === action.payload.id ? { ...action.payload } : todo);
        }
    }
});

export const {updateTodo, addTodo, deleteTodo} = todoSlice.actions;
export default todoSlice.reducer;

store

import { configureStore } from "@reduxjs/toolkit";
import modalSlice from "./state/modalSlice";
import todoSlice from "./state/todoSlice";

export const store = configureStore({
    reducer: {
        modal: modalSlice,
        todo: todoSlice
    },
    middleware: (getDefaultMiddleware) => getDefaultMiddleware({
        serializableCheck: false
    }),
});
export type RootType = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

Это функции, которые вызывают Redux dispatch

const dispatch = useDispatch();
    const list = useSelector((state: RootType) => state.todo);
    const [editableTodo, setEditableTodo] = useState(temp);
    const [isEditable, setIsEditAble] = useState(false);

    const updateTodoItem = () => {
        if(editableTodo != null && editableTodo.id != null && editableTodo.id != "" && editableTodo.task != null && editableTodo.task != "" && editableTodo.completed != null)
            dispatch(updateTodo(editableTodo));
        toggleEdit();
    }

    const deleteTodoItem = () => {
        if(editableTodo != null && editableTodo?.id != null) dispatch(deleteTodo(editableTodo));
        toggleEdit();
    }

    const toggleEdit = (todo?: Todo, save: boolean = false) => {
        if(!editableTodo && todo != null) {
            setEditableTodo(todo);
            setIsEditAble(true);
        }
        else{
            if(save) updateTodoItem();
            setIsEditAble(false);
            setEditableTodo(null);
        }
    }

Я пытался обновить всё состояние, а также найдя точный элемент. Я использовал current(state), поскольку печать состояния выводит ProxyArray длиной 1

.

Ответ или решение

Вам предстоит разобраться с проблемой обновления состояния в вашем приложении React с использованием Redux. Давайте подробно проанализируем предоставленный код и выясним, что могло пойти не так при обновлении списка задач.

Причины, по которым Redux не обновляет список правильно:

  1. Неверное использование состояния в редьюсере:
    В некоторых ваших редьюсерах вы пытаетесь переназначить переменную state, вместо того чтобы изменять само состояние. В Redux Toolkit, который основан на Immer, вы можете изменять state напрямую, и это будет работать корректно.

  2. Отсутствие возвращаемого значения в редьюсерах:
    Некоторые редьюсеры, такие как updateTodo и deleteTodo, не имеют корректной логики изменения состояния. Вам не нужно присваивать новое значение state. Вместо этого просто модифицируйте state напрямую.

  3. Использование ProxyArray:
    Это происходит из-за того, что состояние, возвращаемое из useSelector, относится к типу Proxy, и если вы пытаетесь его распечатать без преобразования, это может выглядеть не так, как вы ожидаете. Это нормально для структур данных, использующих Immer, и обычно не должно вызывать проблем.

Рекомендации по обновлению вашего редьюсера

Давайте очистим ваши редьюсеры, чтобы они правильно изменяли состояние:

const todoSlice = createSlice({
    name: "todoSlice",
    initialState,
    reducers: {
        updateTodo: (state, action: PayloadAction<Todo>) => {
            const index = state.findIndex(todo => todo.id === action.payload.id);
            if (index !== -1) {
                state[index] = { ...state[index], ...action.payload }; // Обновите только нужные поля
            }
            console.log(state);
        },
        updateTodoTask: (state, action: PayloadAction<Todo>) => {
            const index = state.findIndex(todo => todo.id === action.payload.id);
            if (index !== -1) {
                state[index] = { ...state[index], ...action.payload }; // Будьте внимательны к тому, что обновляете
            }
        },
        addTodo: (state, action: PayloadAction<{ task: string, completed: boolean }>) => {
            const id = String(Math.max(...state.map(todo => parseInt(todo.id))) + 1);
            const todo: Todo = { id, task: action.payload.task, completed: action.payload.completed };
            state.push(todo);
        },
        deleteTodo: (state, action: PayloadAction<Todo>) => {
            const index = state.findIndex(todo => todo.id === action.payload.id);
            if (index !== -1) {
                state.splice(index, 1); // Удалить задачу из состояния
            }
        }
    }
});

Правильный вызов dispatch

Также убедитесь, что ваши функции вызова dispatch производятся корректно, как вы уже делали это. Проверьте наличие корректных значений в editableTodo, прежде чем вызывать dispatch.

Советы по отладке

  1. Отладка состояния: Используйте Redux DevTools для отслеживания состояния вашего хранилища и действий, которые его изменяют.
  2. Печать состояния: Вставьте дополнительные console.log в редьюсеры для контроля изменений состояния во время выполнения.
  3. Тестирование отдельных редьюсеров: Создайте тесты для каждого из ваших редьюсеров, чтобы убедиться, что они работают правильно и ожидаемым образом.

Заключение

Используя эти рекомендации, вы сможете настроить правильное обновление состояния в вашем приложении с помощью Redux. Внимательно следите за тем, как вы изменяете состояние, и используйте средства отладки, чтобы убедиться в его корректной работе. Redux Toolkit значительно упрощает работу с состоянием, но требует аккуратного обращения с изменениями данных.

Оцените материал
Добавить комментарий

Капча загружается...