CreateAsyncThunk 错误:操作必须是普通对象。使用自定义中间件进行异步操作

Posted

技术标签:

【中文标题】CreateAsyncThunk 错误:操作必须是普通对象。使用自定义中间件进行异步操作【英文标题】:CreateAsyncThunk Error: Actions must be plain objects. Use custom middleware for async actions 【发布时间】:2020-11-09 07:50:57 【问题描述】:

我目前正在设置我的 RTK (Redux Toolkit) 并进行了一些小测试。这是我的代码:

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('testuser@example.com', 'test123'))
  , [])

  return <div>Auth Test</div>


上面的代码不起作用。我不断收到此错误:

Error: Actions must be plain objects. Use custom middleware for async actions.

在这一行: &gt; 25 | dispatch(authorize('testuser@example.com', 'test123'))

请不要介意我在 useEffect 上触发授权,因为这只是一个测试,以检查是否正在调用端点并检查请求成功后状态是否会更新。 :-D

【问题讨论】:

在我的错误上标记@markerikson。请帮忙 向我们展示您配置商店的代码。有没有应用thunk中间件? 我会更新帖子 【参考方案1】:

我遇到了同样的问题,这是由于我添加了额外的中间件造成的。

@reduxjs/toolkitconfigureStore 有一些默认包含的中间件,但是如果您向middleware 属性添加任何内容,它将覆盖这些默认值。

解决方案是包含默认中间件以及您定义的中间件:

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

注意,使用@reduxjs/toolkit 时无需显式包含redux-thunk,因为它已经是getDefaultMiddleware() 的默认中间件的一部分

【讨论】:

这似乎不是 OP 问题的解决方案。我看到这对于那些不小心覆盖了他们的默认中间件并遇到类似错误的人来说是多么有价值。 RTK团队建议的方式是使用以下middleware: (getDefaultMiddleware) =&gt; getDefaultMiddleware().concat(loggerMiddleware), redux-toolkit.js.org/api/getDefaultMiddleware【参考方案2】:

看起来问题是您没有向商店添加能够处理异步操作的中间件

在您的store/index.js 中尝试类似:

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

【讨论】:

我仍然遇到同样的错误。顺便说一句,这是我的 RTK 版本: - reduxjs/toolkit@1.4.0 - redux@4.0.5 - redux-thunk@2.3.0 - redux-devtools@3.5.0 我有这个: - UNMET PEER DEPENDENCY react- redux@7.2.0 - 错误!缺少对等部门:react-redux@^4.0.0 || ^5.0.0 || ^6.0.0,redux-devtools@3.5.0 需要 hm... 也许改变中间件的顺序,让 thunk 优先?现在将更新我的代码... 当然!我将尝试进一步调查此问题。非常感谢! 还有什么好运@BenBorla ? redux-thunk 默认包含在 RTK 中:redux-toolkit.js.org/usage/…【参考方案3】:

如果有多个参数要传递给动作创建者,则必须将它们传递给对象。 例如,如果我必须将电子邮件和密码作为有效负载发送,我必须将它们发送到如下对象中:

dispatch(authorize(email, password))

【讨论】:

【参考方案4】:

解决此问题的一种方法是使用商店的调度方法。 这样,由于 thunk 默认包含在 Redux Toolkit (RTK) 中,您将可以访问它 - 这应该可以解决您遇到的错误。

试试这个:

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('testuser@example.com', 'test123'))
  , [])

  return <div>Auth Test</div>

【讨论】:

以上是关于CreateAsyncThunk 错误:操作必须是普通对象。使用自定义中间件进行异步操作的主要内容,如果未能解决你的问题,请参考以下文章

调度由 saga 中的 createAsyncThunk 创建的操作时出现打字稿错误

无法从连接的 React 组件触发 createAsyncThunk

Redux ToolKit:是不是可以在由 createAsyncThunk 创建的一个操作中调度来自同一切片的其他操作

一种使用 createAsyncThunk 触发多个异步操作的简洁方法

createAsyncThunk - 更改挂起状态不会导致立即重新渲染

Redux-Toolkit createAsyncThunk Dispatch 显示为未定义