redux “操作必须是普通对象,使用自定义中间件进行异步操作,”即使应用了thunk

j1dl9f46  于 2023-05-18  发布在  其他
关注(0)|答案(2)|浏览(138)

我试图弄清楚为什么我得到“动作必须是普通对象。Use custom middleware for async actions.”(使用自定义中间件进行异步操作)。据我所知,这个问题的正常原因是我的thunk中间件没有应用,因此redux只期望POJO操作,而不是thunk操作。不过,除非我弄错了,我相信我已经这样做了。我还仔细检查了一下,以确保我的thunk action creator实际上返回了一个thunk action。我看了看周围,甚至问了chatgpt,我似乎找不到任何解决这个问题的办法。代码如下:

应用thunk

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import { composeWithDevTools } from 'redux-devtools-extension';

import rootReducer from './services/reducers/root_reducer.js';

// apply logger middleware only in dev env
const composedEnhancer = compose(composeWithDevTools(), applyMiddleware(thunk, logger.default));

const configureStore = (preloadedState = {}) => {
  return createStore(rootReducer, preloadedState, composedEnhancer);
};

export default configureStore;

index.js

import './assets/styles/reset.css';
import './assets/styles/index.css';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import configureStore from './store.js';
import App from './app.js';

const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);
root.render(
  <Router>
    <Provider store={configureStore()}>
      <App />
    </Provider>
  </Router>
)

thunk action

import UserApi from '../api/user_api.js';
import { UserActions } from '../constants/actions.js';
import { displayError } from './error_actions.js';
import userPool from '../../user_pool.js';

export const addUser = (user) => {
  return {
    type: UserActions.addUser,
    payload: user
  };
};

export const register = (registerData) => {
  return async (dispatch) => {
    userPool.signUp(registerData.email, registerData.password, registerData.attributeList, null, (error, result) => {
      if (error) {
        return dispatch(displayError(error));
      } else {
        return dispatch(addUser(result.user));
      }
    });
  }
}

调度形实转换动作

// Called when form is submitted
  const onSubmit = (event) => {
    event.preventDefault();
    const registerParams = {
      email: user.email,
      password: user.password,
      attributeList: []
    };
    delete user.email;
    delete user.password;
    Object.entries(user).forEach(([key, value]) => {
      if (key === "birthdate") {
        const options = { year: 'numeric', month: '2-digit', day: '2-digit' };
        value = value.toLocaleDateString('en-US', options).replace(/\//g, '-');
      }
      let attributeParams = {
        Name: key,
        Value: value
      };
      let cognitoAttribute = new CognitoUserAttribute(attributeParams);
      registerParams.attributeList.push(cognitoAttribute);
    });
    dispatch(register(registerParams));
  };
oug3syen

oug3syen1#

一个潜在的问题是这一行看起来是错误的:

const composedEnhancer = compose(composeWithDevTools(), applyMiddleware(thunk, logger.default));

这一行有三个问题:

  • applyMiddleware应该总是第一个
    • 如果 * 您正在添加devtools安装程序,则应在最后添加
  • 但实际上composeWithDevtools() * 取代 * 独立的compose

所以应该是

const composedEnhancer = composeWithDevtools(applyMiddleware(thunk, logger.default));

我不确定这是错误的原因,但很有可能。

但是,还有一个问题:

你写的Redux逻辑的风格非常过时。
今天,所有的Redux用户 * 应该 * 使用我们的官方Redux Toolkit包来编写他们的Redux代码。它极大地简化了Redux的使用,其中包括您的示例中的一些代码。
特别是,RTK的configureStore API使用已配置的thunk中间件和Redux DevTools设置存储,RTK的createAsyncThunk将为您执行“异步请求的调度操作”。
有关如何使用Redux Toolkit的详细信息,请参阅我们的文档:

vhmi4jdf

vhmi4jdf2#

。。。@markerikson说的话加上。。
onSubmit回调调用dispatch(),并将register()的返回值作为其参数。从register()返回的是一个Promise,而不是一个可序列化的对象。
register()使用dispatch()的返回值来实现(解析),该返回值返回Promise。

相关问题