I have a React application that uses Redux-Toolkit to create slices for my reducers and actions.
I'm trying to create actions that can update and remove values from the store, and they require arguments to be used. I've done this by giving my actions an action: PayloadAction<xxx>
parameter. My slice code is as follows:
import { createSlice } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
interface Todo {
text: string,
complete: boolean,
id: number
}
const initialState: Todo[] = [
{ text: 'Walk the Dog', complete: false, id: 378 },
{ text: 'Eat Dinner', complete: false, id: 912 }
]
export const TodoSlice = createSlice({
name: 'todos',
initialState,
reducers: {
removeTodo: (state, action: PayloadAction<number>) =>
state = state.filter(todo => todo.id != action.payload),
updateText: (state, action: PayloadAction<{ id: number, newText: string }>) =>
state = state.map(todo => todo.id == action.payload.id ? todo :
{ ...todo, text: action.payload.newText}),
addTodo: (state, action: PayloadAction<Todo>) =>
state = [ ...state, action.payload ]
}
})
export const { removeTodo, updateText, addTodo } = TodoSlice.actions
export default TodoSlice.reducer
However, whenever I try to use these actions, I get a few conflicting errors. Providing the action with the intended payload argument produces the Expected 0 but got 1 argument(s)
error. But whenever I don't provide these arguments (useAppDispatch(removeTodo())
by itself), it gives me both Expected 1 argument but got 0
and Expected 0 arguments(s) but got 1
These errors remind me of writing effects with ngrx and angular and how I took like 5 hours to get them working. Turns out I didn't register my new action with the root-store module. Just like that time I'm sure there's something so obvious I'm missing.
Whenever I try to use these actions, I get a few conflicting errors. Providing the action with the intended payload argument produces the
Expected 0 but got 1 argument(s)
error. But whenever I don't provide these arguments (useAppDispatch(removeTodo()
) by itself), it gives me bothExpected 1 argument but got 0
andExpected 0 arguments(s) but got 1
.
You have two things going on here.
The useDispatch
, and by extension your useAppDispatch
because you are using Typescript, doesn't consume any arguments, it returns the store's dispatch
function. Passing an argument here triggers the error "Expected 0 arguments(s) but got 1" because you passed it something it's not expecting.
Call the useAppDispatch
hook and access the dispatch
function.
const dispatch = useAppDispatch();
The "Expected 1 argument but got 0" is caused by not passing an expected argument to the action creator, e.g. removeTodo()
. removeTodo
expects a number to be passed to it, i.e. removeTodo(5)
.
Dispatch the actions to the store and pass the appropriate expected arguments to them.
Examples:
dispatch(removeTodo(5));
dispatch(updateText({
id: 123,
newText: "This is some new Todo text."
}));
dispatch(addTodo({
id: 123,
text: "This is a new Todo.",
completed: false
}));
Additionally, it's an error to reassign the state
in the reducers. Either mutate the state
object or return a new state reference.
export const TodoSlice = createSlice({
name: 'todos',
initialState,
reducers: {
removeTodo: (state, action: PayloadAction<number>) =>
state.filter(todo => todo.id != action.payload),
updateText: (state, action: PayloadAction<{ id: number, newText: string }>) =>
state.map(
todo => todo.id == action.payload.id
? todo
: { ...todo, text: action.payload.newText}
),
addTodo: (state, action: PayloadAction<Todo>) =>
state.concat(action.payload)
}
})