最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - CreateAsyncThunk Error: Actions must be plain objects. Use custom middleware for async actions - Stack Overflow

programmeradmin2浏览0评论

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

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

Share Improve this question edited Jul 20, 2020 at 5:53 BenBorla asked Jul 20, 2020 at 5:10 BenBorlaBenBorla 811 gold badge1 silver badge5 bronze badges 3
  • tagging @markerikson on my error. Please help – BenBorla Commented Jul 20, 2020 at 5:12
  • show us your code where you configure the store. Have you applied the thunk middleware? – Alex Shchur Commented Jul 20, 2020 at 5:27
  • I'll update the post – BenBorla Commented Jul 20, 2020 at 5:52
Add a comment  | 

5 Answers 5

Reset to default 13

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()

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()]
})

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}))

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>
}

This helped me!

getDefaultMiddleware is useful if you want to add some custom middleware, but also still want to have the default middleware added as well:
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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论