@reduxjs/toolkit过滤器列表



详细信息:我使用@reduxjs/toolkit和reactjs来构建一个简单的todo应用程序。我使用@reduxjs/toolkit。我想添加一个过滤列表,按All和completed not completed.

问题:我如何将过滤器列表添加到此待办事项列表(所有和已完成未完成)?

todoSlice.js:

import { createSlice } from '@reduxjs/toolkit';
const todoSlice = createSlice({
name: 'todos',
initialState: {
todos: [
{
id: 1,
completde: false,
title: 'todo 1',
completed: false,
},
{
id: 2,
completde: true,
title: 'todo 2',
completed: false,
},
],
},
reducers: {
addTodo(state, action) {
state.todos.push({
id: new Date().toISOString(),
title: action.payload.title,
});
},
toggleTodo(state, action) {
const toggleTodoItem = state.todos.find(
(todo) => todo.id === action.payload.id
);
toggleTodoItem.completed = !toggleTodoItem.completed;
},
removeTodo(state, action) {
state.todos = state.todos.filter((todo) => todo.id !== action.payload.id);
},
filterTodo(state, action) {
// state.filterKey = action.payload.key;
console.log(action.payload);
},
},
});
const { actions, reducer } = todoSlice;
export const { addTodo, removeTodo, toggleTodo, filterTodo } = actions;
export default reducer;

FilterTodo.js:

import { useDispatch } from 'react-redux';
import { filterTodo } from './todoSlice';
export default function TodoFilter({ key }) {
const dispatch = useDispatch();
return (
<>
<button onClick={dispatch(filterTodo('ALL'))}>All</button>
<button onClick={dispatch(filterTodo('COMPLETED'))}>Completed</button>
<button onClick={dispatch(filterTodo('NOT_COMPLETED'))}>
Not completed
</button>
</>
);
}

TodoList.js:

import TodoItem from './TodoItem';
import { useSelector } from 'react-redux';
export default function TodoList() {
const todos = useSelector((state) => state.todos.todos);
return (
<ul>
{todos.map((todo) => (
<TodoItem key={todo.id} {...todo} />
))}
</ul>
);
}

... ... ....

过滤的几种方法之一是向切片的状态添加一个过滤字符串,然后创建一个基于该字符串的函数来过滤数组,为了避免拼写错误,我喜欢添加一个具有所有可能过滤器的对象,如果您使用typescript,它可以是enum而不是一个对象。看一下:

todoSlice.js:

import { createSlice } from '@reduxjs/toolkit';
// the object to represent the filters
export const filters = {
ALL: "ALL",
COMPLETED: "COMPLETED",
NOT_COMPLETED: "NOT_COMPLETED"
}
const todoSlice = createSlice({
name: 'todos',
initialState: {
todos: [
{
id: 1,
completde: false,
title: 'todo 1',
completed: false,
},
{
id: 2,
completde: true,
title: 'todo 2',
completed: false,
},
],
// default: show all todos
filterBy: filters.ALL
},
reducers: {
addTodo(state, action) {
state.todos.push({
id: new Date().toISOString(),
title: action.payload.title,
});
},
toggleTodo(state, action) {
const toggleTodoItem = state.todos.find(
(todo) => todo.id === action.payload.id
);
toggleTodoItem.completed = !toggleTodoItem.completed;
},
removeTodo(state, action) {
state.todos = state.todos.filter((todo) => todo.id !== action.payload.id);
},
filterBy(state, action) {
state.filterBy = action.payload
},
},
});
const { actions, reducer } = todoSlice;
export const { addTodo, removeTodo, toggleTodo, filterBy } = actions;
export default reducer;

FilterTodo.js:

import { useDispatch } from 'react-redux';
import { filterBy, filters } from './todoSlice';
export default function TodoFilter({ key }) {
const dispatch = useDispatch();
return (
<>
// use the filters object to dispatch the right payload
<button onClick={dispatch(filterBy(filters.ALL))}>All</button>
<button onClick={dispatch(filterBy(filters.COMPLETED))}>Completed</button>
<button onClick={dispatch(filterBy(filters.NOT_COMPLETED))}>
Not completed
</button>
</>
);
}

TodoList.js:

import TodoItem from './TodoItem';
import { useSelector } from 'react-redux';
// don't forget to change the path
import { filters } from 'path/to/todoSlice';
export default function TodoList() {
const todos = useSelector((state) => state.todos.todos);
const filter = useSelector((state) => state.todos.filterBy);

// the function to handle the filter logic
const filteredTodo = () => {
if(filter === filters.COMPLETED) {
return todos.filter(todo => todo.completed);
}
if(filter === filters.NOT_COMPLETED) {
return todos.filter(todo => !todo.completed)
}
// if none of above return all todos
return todos;
}
return (
<ul>
{filteredTodo().map((todo) => (
<TodoItem key={todo.id} {...todo} />
))}
</ul>
);
}

最新更新