I keep getting dispatch error with redux/ typescript. Would be great if someone can help correct the setup I have here:
Store:
import {
configureStore,
combineReducers,
MiddlewareArray,
} from '@reduxjs/toolkit'
import { useDispatch } from 'react-redux'
//import slice as reducer
import userReducer from './features/userSlice'
import heroReducer from './features/heroSlice'
import menuReducer from './features/menuSlice'
import utilsReducer from './features/utilsSlice'
import templatesReducer from './features/templatesSlice'
const rootReducer = combineReducers({
//combine all reducers
user: userReducer,
hero: heroReducer,
menu: menuReducer,
utils: utilsReducer,
templates: templatesReducer,
})
export const store = configureStore({
reducer: rootReducer,
middleware: new MiddlewareArray(),
})
export type AppDispatch = typeof store.dispatch
export const useAppDispatch = () => useDispatch<AppDispatch>()
where the dispatch is happening:
useEffect(() => {
const fetchData = () => {
// TODO
dispatch(fetchUser()). <--- error portion
}
fetchData()
}, [])
user slice:
import { createSlice, createSelector, createAsyncThunk } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import axios from 'axios'
export const fetchUser = createAsyncThunk(
'user/fetchUser',
async (thunkAPI) => {
try {
const response = await axios.get('/api/user', {
headers: {
'Content-Type': 'application/json',
},
})
return response.data
} catch (error) {
// return rejectWithValue({ error: error.message })
return console.log(error.message)
}
}
)
const userSlice = createSlice({
name: 'user',
initialState: {
userData: {},
isSubscribed: false,
},
reducers: {
setUserData: (state: any, action: any) => {
state.userData = action.payload.userData
},
setIsSubscribed: (state: any, action: any) => {
state.isSubscribed = action.payload.isSubscribed
},
},
extraReducers: (builder) => {
builder.addCase(fetchUser.fulfilled, (state: any, action: any) => {
state.userData = action.payload
state.isSubscribed = action.payload.isSubscribed
})
},
})
export const userData = createSelector(
(state: any) => ({
userData: state.userData,
isSubscribed: state.isSubscribed,
}),
(state: any) => state.userData
)
export const { setUserData, setIsSubscribed } = userSlice.actions
export default userSlice.reducer
Not too sure what else is needed to get rid of type errors?
Original error:
Error: Actions must be plain objects. Use custom middleware for async actions.
Type Error on dispatch(fetchUser())
'Argument of type 'AsyncThunkAction<any, void, {}>' is not assignable to parameter of type 'AnyAction''
npm ls redux shows:
CodePudding user response:
Your middleware: new MiddlewareArray()
removes all middleware from the store - while usually a few would be included. Among them is redux-thunk
, which allows for the dispatch of thunks.
Change it to:
export const store = configureStore({
reducer: rootReducer,
})
By the way you also don't need combineReducers
, so you can do
export const store = configureStore({
reducer: {
user: userReducer,
hero: heroReducer,
menu: menuReducer,
utils: utilsReducer,
templates: templatesReducer,
},
})
CodePudding user response:
The issue you have here is that there is no middleware available to receive thunks, specifically the fetchUserUser
thunk that you are dispatching.
The call to new MiddlewareArray()
likely returns an empty middleware array which does not include the thunk middleware.
To introduce such middleware, you can do so in the following ways when configuring your store:
import thunk from 'redux-thunk'
...
export const store = configureStore({
reducer: rootReducer,
middleware: [thunk] // add the thunk middleware
})
OR alternatively, you may use the getDefaultMiddleware
callback, which includes the same thunk middleware from 'redux-thunk' alongside other helpful serializability- and immutability-check middleware in development. Find more docs on this here.
This is what that would look like:
...
export const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware() // includes the thunk middleware
})