Reputation: 81
I am currently setting up my RTK (Redux Toolkit) and did some minor testings. Here's my code:
store/index.js
import { configureStore } from '@reduxjs/toolkit'
import { loginSliceReducer } from './views/page/login/loginSlice'
export default configureStore({
reducer: {
login: loginSliceReducer
}
})
loginSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import ApiService from '../../services/ApiService'
export const authorize = createAsyncThunk(
'api/authorize',
async (email, password) => {
const response = await ApiService.post(email, password)
return response.data
}
)
export const loginSlice = createSlice({
name: 'login',
initialState: {
loading: true,
token: null,
data: []
},
reducers: {
updateState: (state, action) => {
const { payload } = action
switch (payload.type) {
case AUTH_SUCCESS:
state.loading = false
state.token = payload.token
state.data = payload.data
break
default:
}
}
},
extraReducers: {
[authorize.fulfilled]: (state, action) => {
// ... do state update here
}
}
})
export default loginSlice.reducer
login.js
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { authorize } from './loginSlice'
const Login = () => {
const dispatch = useDispatch()
useEffect(() => {
dispatch(authorize('[email protected]', 'test123'))
}, [])
return <div>Auth Test</div>
}
The code above doesn't work. I keep getting this error:
Error: Actions must be plain objects. Use custom middleware for async actions.
On this line:
> 25 | dispatch(authorize('[email protected]', 'test123'))
Please don't mind me triggering the authorize on useEffect, as this is only a test to check if the endpoint is being called and to check if the state will update once the request is successful. :-D
Upvotes: 8
Views: 10079
Reputation: 1120
import { configureStore } from '@reduxjs/toolkit'
import logger from 'redux-logger'
import rootReducer from './reducer'
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
})
The above solution is from official redux toolkit documentation:
https://redux-toolkit.js.org/api/getDefaultMiddleware
Upvotes: 0
Reputation: 1563
one way you can fix this is to use your store's dispatch method. This way, since thunk is included in Redux Toolkit (RTK) by default, you'll have access to that - which should fix the error you're getting.
Try This:
store/index.js
import { configureStore } from '@reduxjs/toolkit'
import { loginSliceReducer } from './views/page/login/loginSlice'
export default const store = configureStore({
reducer: {
login: loginSliceReducer
}
})
const useAppDispatch = () => store.dispatch
export { useAppDispatch }
login.js
import React, { useEffect } from 'react'
import { useSelector} from 'react-redux'
import { authorize } from './loginSlice'
import { useAppDispatch } from './store/index'
const Login = () => {
const dispatch = useAppDispatch()
useEffect(() => {
dispatch(authorize('[email protected]', 'test123'))
}, [])
return <div>Auth Test</div>
}
Upvotes: 0
Reputation: 983
If there are more than one argument to be passed to an action creator, you must pass them inside an object. For example, if I have to send email and password as payload, I will have to send them in an object like below:
dispatch(authorize({email, password}))
Upvotes: 0
Reputation: 9464
I had this same issue and it was caused by the fact that I was adding additional middleware.
@reduxjs/toolkit
's configureStore
has some middleware that is included by default, but if you add anything to the middleware
property, it will overwrite these defaults.
The solution is to include the default middleware along with the middleware you define:
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import { loginSliceReducer } from './views/page/login/loginSlice';
import { otherMiddleware } from './middlewares/some-other-module';
export default configureStore({
reducer: {
login: loginSliceReducer
},
middleware: [ // Because we define the middleware property here, we need to explictly add the defaults back in.
...getDefaultMiddleware(),
otherMiddleware
]
})
Note, there is no need to explicitly include redux-thunk
when using @reduxjs/toolkit
because it is already part of the default middlewares from getDefaultMiddleware()
Upvotes: 13
Reputation: 751
Looks like the problem is that you didn't add to your store a middleware capable of handling async actions
In your store/index.js
try smth like:
import { applyMiddleware } from 'redux';
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
import { loginSliceReducer } from './views/page/login/loginSlice'
import thunk from 'redux-thunk';
export default configureStore({
reducer: {
login: loginSliceReducer
},
middleware: [applyMiddleware(thunk), getDefaultMiddleware()]
})
Upvotes: 0