React-Redux:动作必须是普通对象。使用自定义中间件进行异步操作


84

未处理的拒绝(错误):动作必须是普通对象。使用自定义中间件执行异步操作。

我想在每个帖子中添加评论。因此,当获取帖子运行时,我想为所有帖子调用获取评论API。

export function bindComments(postId) {
  return API.fetchComments(postId).then(comments => {
    return {
      type: BIND_COMMENTS,
      comments,
      postId
    }
  })
}

Answers:


64

您必须在异步请求结束后分派。

这将工作:

export function bindComments(postId) {
    return function(dispatch) {
        return API.fetchComments(postId).then(comments => {
            // dispatch
            dispatch({
                type: BIND_COMMENTS,
                comments,
                postId
            });
        });
    };
}

4
它在下面提到,但是您需要具有redux
架构的

1
@sadiq为什么必须强制执行操作?我不想将任何东西分派到商店,但我没有将其定义为“异步分派”的异步操作遇到了同样的问题。
索拉基姆

12

对于那些可能会像我一样遗漏简单细节的未来求职者,就我而言,我只是忘了用括号来调用我的动作函数。

actions.js:

export function addNewComponent() {
  return {
    type: ADD_NEW_COMPONENT,
  };
}

myComponent.js:

import React, { useEffect } from 'react';
import { addNewComponent } from '../../redux/actions';

  useEffect(() => {
    dispatch(refreshAllComponents); // <= Here was what I've missed.
  }, []);

我忘了用调度动作函数()。因此,这样做解决了我的问题。

  useEffect(() => {
    dispatch(refreshAllComponents());
  }, []);

同样,这可能与OP的问题无关,但是我希望我能帮助遇到与我的问题相同的人。


1
谢谢你 容易错过。没有做任何异步的事情,所以我知道这是我错过的简单事情!
Taylor A. Leach

11

没有中间件,就无法在操作中使用提取。动作必须是普通对象。您可以使用诸如redux-thunk或redux-saga之类的中间件进行获取,然后分派另一个操作。

这是一个使用redux-thunk中间件的异步操作示例。

export function checkUserLoggedIn (authCode) {
 let url = `${loginUrl}validate?auth_code=${authCode}`;
  return dispatch => {
    return fetch(url,{
      method: 'GET',
      headers: {
        "Content-Type": "application/json"
      }
      }
    )
      .then((resp) => {
        let json = resp.json();
       if (resp.status >= 200 && resp.status < 300) {
          return json;
        } else {
          return json.then(Promise.reject.bind(Promise));
        }
      })
      .then(
        json => {
          if (json.result && (json.result.status === 'error')) {
            dispatch(errorOccurred(json.result));
            dispatch(logOut());
          }
          else{
            dispatch(verified(json.result));
          }
        }
      )
      .catch((error) => {
        dispatch(warningOccurred(error, url));
      })
  }
}

抱歉,我认为您没有使用中间件。@sadiq提到了那里的调度问题。
Sinapcs

6

利用箭头功能可以提高代码的可读性。不需要返回任何内容API.fetchComments,当请求完成时,Api调用将是异步的,then它将获得响应,在那里您只需要dispatch输入类型和数据即可。

下面的代码通过使用Arrow函数完成相同的工作。

export const bindComments = postId => {
  return dispatch => {
    API.fetchComments(postId).then(comments => {
      dispatch({
        type: BIND_COMMENTS,
        comments,
        postId
      });
    });
  };
};

6

错误只是要求您在中间插入一个中间件,以帮助处理异步操作。

您可以通过以下方式实现:

npm我redux-thunk

        Inside index.js

import thunk from "redux-thunk" 
        
...createStore(rootReducers, applyMiddleware(thunk));

现在,异步操作将在您的函数中起作用。


2

我遇到了与错过添加composeEnhancers相同的问题。设置完成后,您可以查看动作创建者。如果未同时设置,则会出现此错误。

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  rootReducer,
  composeEnhancers(applyMiddleware(thunk))
);

0

动作定义

const selectSlice = () => {
  return {
    type: 'SELECT_SLICE'
  }
};

动作派遣

store.dispatch({
  type:'SELECT_SLICE'
});

确保定义的动作的对象结构与分派的动作相同。就我而言,在调度操作时,没有将type分配给property type

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.