redux TypeError:todos.map不是我的todo中的函数

khbbv19g  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(101)

我写了一个react应用程序todolist使用redux工具包和ts,应用程序编译正常,直到我删除一个项目,删除后立即出现错误TodoList.tsx:9 Uncaught (in promise) TypeError: todos.map is not a function我不知道如何修复它,并会很乐意得到帮助。下面是我的todoList组件的代码

import { useSelector } from 'react-redux';
import TodoItem from './TodoItem';
import React from 'react';

const TodoList: React.FC = () => {
    const todos = useSelector((state: RootState) => state.todos.todos);

    return (
        <ul>
            {todos.map((todo) => (
                <TodoItem defaultTitle={''} key={todo.id} {...todo} />
            ))}
        </ul>
    );
};

export default TodoList;

interface RootState {
    todos: {
        todos: Todo[];
    };
}

export interface Todo {
    id: number;
    title: string;
    completed: boolean;
}

这是我的todoSlice

import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
import  axios  from 'axios';

interface Todo {
    userId: number,
    id: number,
    title: string,
    completed: boolean
}

interface TodoState {
    todos: Todo[];
    status: string | null;
    error: string | null;
}

export interface TodoReqest {
    userId: number,
    title: string,
    completed: boolean
}

export const fetchTodos = createAsyncThunk(
    'todo/fetchTodos',
    async function() {
        const response = await axios.get('http://localhost:3004/todos')
        const data = await response.data;
        return data;
    }
)

export const removeTodosThunk = createAsyncThunk<Todo[], number>(
    'todo/fetchTodos',
    async function(id) {
        const {data} = await axios.delete('http://localhost:3004/todos/' + id.toString())
        return data;
    }
)

export const addTodosThunk = createAsyncThunk<Todo, TodoReqest>(
    'todo/addTODO',
    async function(body) {
        const response = await axios.post('http://localhost:3004/todos/', body);
        const { data } = response;
        return data;
    }
)

const todoSlice = createSlice({
    name: 'todos',
    initialState: {
        todos: [],
        status: null,
        error: null,
    } as TodoState,
    reducers: {
        addTodo: (state, {payload}: { payload: Todo }) => {
            state.todos.push(payload);
        },
        toggleComplete: (state, action: PayloadAction<{id: number}>) => {
            const toggledTodo = state.todos.find(todo => todo.id === action.payload.id);
            if (toggledTodo) {
                toggledTodo.completed = !toggledTodo.completed;
            }
        },
        removeTodo: (state, action: PayloadAction<{id: number}>) => {
            state.todos = state.todos.filter(todo => todo.id !== action.payload.id);
        }
    },
    extraReducers: (builder) => {
        builder.addCase(fetchTodos.pending, (state) => {
            state.status = 'loading';
            state.error = null;
        })
        .addCase(fetchTodos.fulfilled, (state, action) => {
            state.status = 'resolved';
            state.todos = action.payload;
        })
        .addCase(addTodosThunk.fulfilled, (state, { payload } : { payload: Todo }) => {
            console.log(payload);
            state.todos.push(payload);
          })
        .addCase(fetchTodos.rejected, (state, action) => {
            state.status = 'rejected';
        });
    }
});

export const { addTodo, toggleComplete, removeTodo } = todoSlice.actions;

export default todoSlice.reducer;

这是我的商店组件

import { configureStore } from '@reduxjs/toolkit';
import todoReducer from './todoSlice';
import { useDispatch, useSelector } from 'react-redux';

const store = configureStore({
  reducer: {
    todos: todoReducer,
  },
});
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;
export const useAppDispatch: () => AppDispatch = useDispatch;

export default store;
import { useDispatch } from 'react-redux';
import { toggleComplete, removeTodosThunk } from '../store/todoSlice';
import React from 'react';
import { Dispatch } from 'redux';

interface TodoItemProps {
  defaultTitle: string;
  id: number;
  title: string;
  completed: boolean;
}

const TodoItem: React.FC<TodoItemProps> = ({ id, title, completed }) => {
  const dispatch = useDispatch<Dispatch<any>>();

  const handleToggleComplete = (): void => {
    dispatch<any>(toggleComplete({id}));
  };

  const handleRemoveTodo = (): void => {
    dispatch<any>(removeTodosThunk(id));
  };

  return (
    <li>
      <input
        type='checkbox'
        checked={completed}
        onChange={handleToggleComplete}
      />
      <span>{title}</span>
      <button onClick={handleRemoveTodo}>&times;</button>
    </li>
  );
};

export default TodoItem;
sd2nnvve

sd2nnvve1#

删除项目后,您的“todos”不是数组,导致map方法失败。尝试修改'removeTodo' reducer以返回一个排除已删除'todo'的新数组,而不是使用filter修改原始数组。

相关问题