I tried making a user authentication using redux toolkit in Nextjs with Typescript but I keep getting the following error when dispatching an action.
Type error: Argument of type 'AsyncThunkAction<any, SigninParams, AsyncThunkConfig>' is not assignable to parameter of type 'AnyAction'.
This is my signin.tsx file
import { useState } from 'react'
import { useDispatch } from 'react-redux'
import { getUser } from '../../store/slices/userSlice'
const Signin = () => {
const dispatch = useDispatch()
const [userData, setUserData] = useState({
email: '',
password: '',
})
const signinHandler = async (e: any) => {
e.preventDefault()
dispatch(getUser({ userData }))
}
return (
<div className='flex items-center justify-center w-screen h-screen'>
<form
onSubmit={signinHandler}
className='border p-5 flex flex-col items-center justify-center'>
<input
type='email'
onChange={(e) =>
setUserData((prev) => ({
...prev,
email: e.target.value,
}))
}
/>
<input
type='password'
onChange={(e) =>
setUserData((prev) => ({
...prev,
password: e.target.value,
}))
}
/>
<button>Signin</button>
</form>
</div>
)
}
export default Signin
This is what the userSlice.ts file looks like
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import dbConnect from '../../lib/dbConnect'
import axios from 'axios'
export interface UserState {
status: 'idle' | 'loading' | 'failed'
user: object
error: string | null | object
}
interface SigninParams {
email: string
password: string
}
// Default state object with initial values.
const initialState: UserState = {
status: 'idle',
user: {},
error: null,
} as const
// Thunks
export const getUser = createAsyncThunk(
'user/signin',
async (params: SigninParams) => {
await dbConnect()
const { email, password } = params
const config = {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
}
const { data } = await axios.post(
'/api/signin',
{ email, password },
config
)
localStorage.setItem('userInfo', JSON.stringify(data))
localStorage.setItem('token', data.token)
return data
}
)
//Slice
export const userSlice = createSlice({
name: 'user',
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(getUser.pending, (state) => {
state.status = 'loading'
state.error = null
})
builder.addCase(getUser.fulfilled, (state, { payload }) => {
state.status = 'idle'
state.user = payload
})
builder.addCase(getUser.rejected, (state, { payload }) => {
if (payload) state.error = payload
state.status = 'failed'
})
},
})
export const getUserState = (state: { user: UserState }) => state.user
// export const { setName, setEmail } = userSlice.actions
export default userSlice.reducer
And here is the store.ts file
import { configureStore } from '@reduxjs/toolkit'
import userSlice from './slices/userSlice'
import {
useDispatch as useDispatchBase,
useSelector as useSelectorBase,
} from 'react-redux'
export const store = configureStore({
reducer: {
user: userSlice,
},
})
export type RootState = ReturnType<typeof store.getState>
type AppDispatch = typeof store.dispatch
export const useDispatch = () => useDispatchBase<AppDispatch>()
export const useSelector = <TSelected = unknown>(
selector: (state: RootState) => TSelected
): TSelected => useSelectorBase<RootState, TSelected>(selector)
I followed the examples in this and this tutorial for setting up redux toolkit with typescript in NextJs.