Answer the question
In order to leave comments, you need to log in
What is the best way to filter a list in react @reduxjs/toolkit?
I am learning react, making a simple todo list with @reduxjs/toolkit, and the question arose of how to filter tasks more correctly.
todoSlice.js
without filtering:import { createSlice } from '@reduxjs/toolkit'
const todoSlice = createSlice({
name: 'todos',
initialState: {
todos: [],
todosFilter: [],
ident: 0,
keyFilter: 'all'
},
reducers: {
add (state, action) {
state.todos.push({
id: state.ident,
title: action.payload.title,
completed: false
})
state.ident = state.ident + 1
},
remove (state, action) {
state.todos = state.todos.filter(todo => todo.id !== action.payload.id)
},
toggle (state, action) {
const editTodo = state.todos.find(todo => todo.id === action.payload.id)
editTodo.completed = !editTodo.completed
}
}
})
export const { add, remove, toggle } = todoSlice.actions
export default todoSlice.reducer
todoSlice.js
with filtering through an additional array with filtered elements:import { createSlice } from '@reduxjs/toolkit'
function filtered (key, todos) {
return todos.filter(todo => {
if (key === 'all') return true
if (key === 'completed' && todo.completed) return true
if (key === 'uncompleted' && !todo.completed) return true
})
}
const todoSlice = createSlice({
name: 'todos',
initialState: {
todos: [],
todosFilter: [],
ident: 0,
keyFilter: 'all'
},
reducers: {
add (state, action) {
state.todos.push({
id: state.ident,
title: action.payload.title,
completed: false
})
state.todosFilter = filtered(state.keyFilter, state.todos)
state.ident = state.ident + 1
},
remove (state, action) {
state.todos = state.todos.filter(todo => todo.id !== action.payload.id)
// Фильтрация после удаления
state.todosFilter = filtered(state.keyFilter, state.todos)
},
toggle (state, action) {
const editTodo = state.todos.find(todo => todo.id === action.payload.id)
editTodo.completed = !editTodo.completed
// Фильтрация после смены выполнения задачи
state.todosFilter = filtered(state.keyFilter, state.todos)
},
filter (state, action) {
state.keyFilter = action.payload.key
state.todosFilter = filtered(state.keyFilter, state.todos)
}
}
})
export const { add, remove, toggle, filter } = todoSlice.actions
export default todoSlice.reducer
todoSlice.js
filtering with a value inside an object:import { createSlice } from '@reduxjs/toolkit'
function filtered (key, todo) {
todo.validFilter = false
if (key === 'all') todo.validFilter = true
if (key === 'completed' && todo.completed) todo.validFilter = true
if (key === 'uncompleted' && !todo.completed) todo.validFilter = true
return todo
}
const todoSlice = createSlice({
name: 'todos',
initialState: {
todos: [],
ident: 0,
keyFilter: 'all'
},
reducers: {
add (state, action) {
const newTodo = {
id: state.ident,
title: action.payload.title,
completed: false,
validFilter: false
}
const modNewTodo = filtered(state.keyFilter, newTodo)
state.todos.push(modNewTodo)
state.ident = state.ident + 1
},
remove (state, action) {
state.todos = state.todos.filter(todo => todo.id !== action.payload.id)
},
toggle (state, action) {
const editTodo = state.todos.find(todo => todo.id === action.payload.id)
editTodo.completed = !editTodo.completed
filtered(state.keyFilter, editTodo)
},
filter (state, action) {
state.keyFilter = action.payload.key
state.todos = state.todos.map(todo => {
return filtered(state.keyFilter, todo)
})
}
}
})
export const { add, remove, toggle, filter } = todoSlice.actions
export default todoSlice.reducer
const TodoList = () => {
const listTodo = useSelector(state => state.todos.todos)
return (
<ul className='todo-list'>
{ listTodo.map(todo => {
if (todo.validFilter === false) return null
return <TodoItem key={todo.id} {...todo} />
})
}
</ul>
)
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question