我写了一个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}>×</button>
</li>
);
};
export default TodoItem;
1条答案
按热度按时间sd2nnvve1#
删除项目后,您的“todos”不是数组,导致map方法失败。尝试修改'removeTodo' reducer以返回一个排除已删除'todo'的新数组,而不是使用filter修改原始数组。