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

IT技术 reactjs react-redux
2021-04-08 05:05:34

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

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

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

您必须在异步请求结束后进行调度。

这会起作用:

export function bindComments(postId) {
    return function(dispatch) {
        return API.fetchComments(postId).then(comments => {
            // dispatch
            dispatch({
                type: BIND_COMMENTS,
                comments,
                postId
            });
        });
    };
}
@sadiq 为什么必须分派动作?我在异步操作中遇到了同样的问题,我没有将其定义为“异步调度”,尽管我不想将任何东西调度到商店。
2021-05-31 05:05:34
它在下面提到,但你需要有 redux-thunk 中间件才能工作
2021-06-03 05:05:34

对于像我这样可能放弃简单细节的未来寻求者,在我的情况下,我只是忘记用括号调用我的动作函数。

动作.js:

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

我的组件.js:

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

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

我忘记用(). 所以这样做解决了我的问题。

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

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

哦,谢谢。我犯了同样的错误:)
2021-06-02 05:05:34
谢谢你。容易错过。没有做任何异步的事情,所以我知道这是我错过的一些简单的事情!
2021-06-18 05:05:34

该错误只是要求您在两者之间插入一个中间件,这将有助于处理异步操作。

你可以这样做:

npm 我 redux-thunk

        Inside index.js

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

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

我正在使用createSliceasyncThunk经过这么多问题和答案,您的答案奏效了。谢谢。
2021-05-25 05:05:34

如果没有中间件,您就无法在操作中使用 fetch。动作必须是普通对象。你可以使用像 redux-thunk 或 redux-saga 这样的中间件来做 fetch 然后分派另一个动作。

这是使用 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 提到它是那里的调度问题。
2021-06-18 05:05:34

利用箭头函数提高代码的可读性。不需要返回任何东西API.fetchComments,Api 调用是异步的,当请求完成时then就会得到响应,你只需要dispatch输入和数据。

下面的代码通过使用箭头函数来完成同样的工作。

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