在 createSlice 中使用 reducer 从 redux 状态的数组中删除元素
Delete element from array in redux state using a reducer in createSlice
我已经为这个问题绞尽脑汁了一段时间,如有任何帮助,我们将不胜感激。
我正在将 React 与 Redux Toolkit 一起使用,我正在努力让 React 从我的 UI 中删除 'todo',即使 Redux 正在按预期响应。在 Redux Developer Tools 中,removeTodo 按预期工作,从 todos 数组状态中删除了一个待办事项,但 React 没有跟随,因此我的 UI 不会随之改变。我的 addTodo 操作在 React 和 Redux 中都按预期工作。
当我单击调用 removeTodo 调度的按钮时,我当前的代码为我提供了以下错误。
TypeError: Cannot read property 'length' of undefined
App
C:/Users/joeee/Documents/redux-middleware/src/app/App.js:13
10 |
11 | return (
12 | <div style={divStyles}>
> 13 | <TodosForm />
| ^ 14 | {todos.length > 0 && <TodoList />}
15 | </div>
16 | )
View compiled
▶ 19 stack frames were collapsed.
应该注意的是,当我的 todos 数组状态的长度 > 0 时,我只在我的 TodoList 组件中渲染,因为我不希望在没有 todos 时渲染该组件。我是 React 和 Redux 的新手,可能有一个非常简单的解决方案,但据我所知,当调用 removeTodo 时,todos 数组状态被完全删除,而不是仅仅返回那些 id 不等于传入的 id 的状态. 这就是为什么我假设我得到的错误是告诉我它无法读取未定义的 .length 因为我的 todos 状态现在是空的。
我删除了 TodoList 渲染需要大于 0 的 todos.length 的要求,但后来我得到了无法读取 TodoList 中未定义(我的待办事项状态)的 .map 的错误对我来说,我的整个待办事项状态似乎都被删除了。
这是我的 todosSlice:
import { createSlice } from '@reduxjs/toolkit';
export const todosSlice = createSlice({
name: 'todos',
initialState: {
todos: [],
},
reducers: {
addTodo: (state, action) => {
const { id, task } = action.payload;
state.todos.push({ id, task })
},
removeTodo: (state, action) => {
// console.log(state.todos);
const { id } = action.payload;
// console.log(id);
return state.todos.filter(item => item.id !== id);
}
},
});
export const selectTodos = state => state.todos.todos;
export const { addTodo, removeTodo } = todosSlice.actions;
export default todosSlice.reducer;
App.js:
import React from 'react';
import { useSelector } from 'react-redux';
import TodosForm from '../components/TodosForm';
import TodoList from '../components/TodoList';
import { selectTodos } from '../features/todosSlice';
export const App = () => {
const todos = useSelector(selectTodos);
// console.log(todos.length);
return (
<div style={divStyles}>
<TodosForm />
{todos.length > 0 && <TodoList />}
</div>
)
}
export default App;
TodoList.js
import React from 'react';
import { useSelector } from 'react-redux';
import { selectTodos } from '../features/todosSlice';
import Todos from './Todos';
const TodoList = () => {
const todos = useSelector(selectTodos);
// console.log(todos);
return (
<div style={divStyles}>
<h3 style={headerStyles}>Your Todos: </h3>
{todos.map(todo => <Todos key={todo.id} task={todo.task} id={todo.id} />)}
</div>
)
}
export default TodoList
Todos.js
import React from 'react';
import { useDispatch } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons'
import { faEdit } from '@fortawesome/free-solid-svg-icons'
import { removeTodo } from '../features/todosSlice';
const Todos = ({ task, id }) => {
const dispatch = useDispatch();
const handleDeleteClick = () => {
dispatch(removeTodo({id: id}));
}
return (
<div style={divStyles}>
<li style={listStyles}>{task}</li>
<div>
<button className="faEditIcon" style={btnStyles}><FontAwesomeIcon icon={faEdit}/></button>
<button className="faDeleteIcon" style={btnStyles} onClick={handleDeleteClick}><FontAwesomeIcon icon={faTrashAlt}/></button>
</div>
</div>
)
}
export default Todos;
还有我的store.js
import { configureStore } from '@reduxjs/toolkit';
import todosSliceReducer from '../features/todosSlice';
export default configureStore({
reducer: {
todos: todosSliceReducer,
},
});
你能不能像下面这样更新 removeTodo 看看。
removeTodo: (state, action) => {
// console.log(state.todos);
const { id } = action.payload;
// console.log(id);
state.todos = state.todos.filter(item => item.id !== id)
}
我已经为这个问题绞尽脑汁了一段时间,如有任何帮助,我们将不胜感激。
我正在将 React 与 Redux Toolkit 一起使用,我正在努力让 React 从我的 UI 中删除 'todo',即使 Redux 正在按预期响应。在 Redux Developer Tools 中,removeTodo 按预期工作,从 todos 数组状态中删除了一个待办事项,但 React 没有跟随,因此我的 UI 不会随之改变。我的 addTodo 操作在 React 和 Redux 中都按预期工作。
当我单击调用 removeTodo 调度的按钮时,我当前的代码为我提供了以下错误。
TypeError: Cannot read property 'length' of undefined
App
C:/Users/joeee/Documents/redux-middleware/src/app/App.js:13
10 |
11 | return (
12 | <div style={divStyles}>
> 13 | <TodosForm />
| ^ 14 | {todos.length > 0 && <TodoList />}
15 | </div>
16 | )
View compiled
▶ 19 stack frames were collapsed.
应该注意的是,当我的 todos 数组状态的长度 > 0 时,我只在我的 TodoList 组件中渲染,因为我不希望在没有 todos 时渲染该组件。我是 React 和 Redux 的新手,可能有一个非常简单的解决方案,但据我所知,当调用 removeTodo 时,todos 数组状态被完全删除,而不是仅仅返回那些 id 不等于传入的 id 的状态. 这就是为什么我假设我得到的错误是告诉我它无法读取未定义的 .length 因为我的 todos 状态现在是空的。
我删除了 TodoList 渲染需要大于 0 的 todos.length 的要求,但后来我得到了无法读取 TodoList 中未定义(我的待办事项状态)的 .map 的错误对我来说,我的整个待办事项状态似乎都被删除了。
这是我的 todosSlice:
import { createSlice } from '@reduxjs/toolkit';
export const todosSlice = createSlice({
name: 'todos',
initialState: {
todos: [],
},
reducers: {
addTodo: (state, action) => {
const { id, task } = action.payload;
state.todos.push({ id, task })
},
removeTodo: (state, action) => {
// console.log(state.todos);
const { id } = action.payload;
// console.log(id);
return state.todos.filter(item => item.id !== id);
}
},
});
export const selectTodos = state => state.todos.todos;
export const { addTodo, removeTodo } = todosSlice.actions;
export default todosSlice.reducer;
App.js:
import React from 'react';
import { useSelector } from 'react-redux';
import TodosForm from '../components/TodosForm';
import TodoList from '../components/TodoList';
import { selectTodos } from '../features/todosSlice';
export const App = () => {
const todos = useSelector(selectTodos);
// console.log(todos.length);
return (
<div style={divStyles}>
<TodosForm />
{todos.length > 0 && <TodoList />}
</div>
)
}
export default App;
TodoList.js
import React from 'react';
import { useSelector } from 'react-redux';
import { selectTodos } from '../features/todosSlice';
import Todos from './Todos';
const TodoList = () => {
const todos = useSelector(selectTodos);
// console.log(todos);
return (
<div style={divStyles}>
<h3 style={headerStyles}>Your Todos: </h3>
{todos.map(todo => <Todos key={todo.id} task={todo.task} id={todo.id} />)}
</div>
)
}
export default TodoList
Todos.js
import React from 'react';
import { useDispatch } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons'
import { faEdit } from '@fortawesome/free-solid-svg-icons'
import { removeTodo } from '../features/todosSlice';
const Todos = ({ task, id }) => {
const dispatch = useDispatch();
const handleDeleteClick = () => {
dispatch(removeTodo({id: id}));
}
return (
<div style={divStyles}>
<li style={listStyles}>{task}</li>
<div>
<button className="faEditIcon" style={btnStyles}><FontAwesomeIcon icon={faEdit}/></button>
<button className="faDeleteIcon" style={btnStyles} onClick={handleDeleteClick}><FontAwesomeIcon icon={faTrashAlt}/></button>
</div>
</div>
)
}
export default Todos;
还有我的store.js
import { configureStore } from '@reduxjs/toolkit';
import todosSliceReducer from '../features/todosSlice';
export default configureStore({
reducer: {
todos: todosSliceReducer,
},
});
你能不能像下面这样更新 removeTodo 看看。
removeTodo: (state, action) => {
// console.log(state.todos);
const { id } = action.payload;
// console.log(id);
state.todos = state.todos.filter(item => item.id !== id)
}