【问题标题】:Why do I get a 'Actions must be plain objects' error?为什么我会收到“操作必须是普通对象”错误?
【发布时间】:2018-09-22 02:01:15
【问题描述】:

我只是在学习 react-redux 并试图触发一个 thunk,这是 thunk:

const getRepos = dispatch => {
  try {
    const url = `https://api.github.com/users/reduxjs/repos?sort=updated`;
    fetch(url)
      .then(response => response.json())
      .then(json => {
        console.log("thunk: getrepos data=", json);
      });
  } catch (error) {
    console.error(error);
  }
};

我将我的组件连接到商店:

const bla = dispatch =>
  bindActionCreators(
    {
      geklikt,
      getRepos
    },
    dispatch
  );

const Container = connect(
  null,
  bla
)(Dumb);

当我触发 getRepos thunk 时,我得到:

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

可能是什么问题?我包括中间件? link to code sandbox

【问题讨论】:

    标签: reactjs react-redux redux-thunk


    【解决方案1】:

    请重构您的应用程序结构,它都在一个文件中,并且极难阅读。

    需要考虑的事项:

    与此同时,这是一个工作版本:https://codesandbox.io/s/oxwm5m1po5

    actions/index.js

    import { GEKLIKT } from "../types";
    
    export const getRepos = () => dispatch =>
      fetch(`https://api.github.com/users/reduxjs/repos?sort=updated`)
        .then(res => res.json())
        .then(data => dispatch({ type: GEKLIKT, payload: data }))
        .catch(err => console.error(err.toString()));
    
    /*
      export const getRepos = () => async dispatch => {
        try {
          const res = await fetch(`https://api.github.com/users/reduxjs/repos?sort=updated`)
          const data = await res.json();
          dispatch({ type: GEKLIKT, payload: data }))
        } catch (err) { console.error(err.toString())}
      }
    */
    

    components/App.js

    import React from "react";
    import Dumb from "../containers/Dumb";
    
    export default () => (
      <div className="App">
        <Dumb />
      </div>
    );
    

    容器/Dumb.js

    import React from "react";
    import { connect } from "react-redux";
    import { getRepos } from "../actions";
    
    let Dumb = ({ data, getRepos }) => (
      <div>
        hi there from Dumb
        <button onClick={getRepos}>hier</button>
        <pre>
          <code>{JSON.stringify(data, null, 4)}</code>
        </pre>
      </div>
    );
    
    export default connect(
      state => ({ data: state.data }),
      { getRepos }
    )(Dumb);
    

    reducers/index.js

    import { combineReducers } from "redux";
    import { GEKLIKT } from "../types";
    
    const klikReducer = (state = {}, { payload, type }) => {
      switch (type) {
        case GEKLIKT:
          return { ...state, data: payload };
        default:
          return state;
      }
    };
    
    export default combineReducers({
      data: klikReducer
    });
    

    root/index.js

    import React from "react";
    import { createStore, applyMiddleware } from "redux";
    import { Provider } from "react-redux";
    import thunk from "redux-thunk";
    import rootReducer from "../reducers";
    import App from "../components/App";
    
    const store = createStore(rootReducer, applyMiddleware(thunk));
    
    export default () => (
      <Provider store={store}>
        <App />
      </Provider>
    );
    

    types/index.js

    export const GEKLIKT = "GEKILKT";
    

    index.js

    import React from "react";
    import { render } from "react-dom";
    import App from "./root";
    import "./index.css";
    
    render(<App />, document.getElementById("root"));
    

    【讨论】:

    • 很好的答案,但很快的问题:为什么 actions/index.js 以 'export const getRepos = () => dispatch =>' 开头?为什么'export const getRepos = dispatch => ...'不正确?
    • 主要与action如何通过thunk有关。 action 函数从调用它的地方接受参数,例如this.props.action(value),并从 thunk 中间件函数 thunk(this.props.action(value), dispatch, getState) 接收额外参数。简单来说,它是一个包裹在另一个函数周围的函数……因此,有两个函数声明。至少,这是我的理解(结构可能有误)。
    【解决方案2】:

    您兑现了承诺。 Promise 不是普通对象,因此返回的操作不会是普通对象,因此会出现错误。

    由于您使用的是 thunk 中间件,因此您的操作可以是函数,这就是您的操作方法。

      const GET_REPOS_REQUEST = "GET_REPOS_REQUEST";
      const GET_REPOS_SUCCESS = "GET_REPOS_SUCCESS";
      const GET_REPOS_ERROR = "GET_REPOS_ERROR";
      export function getRepos() {
          return function action(dispatch) {
            dispatch({type: GET_REPOS})
           const url = `https://api.github.com/users/reduxjs/repos?sort=updated`;
           const request = fetch(url);
           return request.then(response => response.json())
            .then(json => {
                console.log("thunk: getrepos data=", json);
                dispatch({type: GET_REPOS_SUCCESS, json});
            })
           .then(err => {
                dispatch({type: GET_REPOS_ERROR, err});
                console.log(“error”, err);
           });
      };
      }
    

    箭头函数方式:

    export getRepos = () =>{
      return action = dispatch => {
        dispatch({type: GET_REPOS})
       const url = `https://api.github.com/users/reduxjs/repos?sort=updated`;
       const request = fetch(url);
       return request.then(response => response.json())
        .then(json => {
            console.log("thunk: getrepos data=", json);
            dispatch({type: GET_REPOS_SUCCESS, json});
        })
       .then(err => {
            console.log(“error”, err);
            dispatch({type: GET_REPOS_ERROR, err});
       });
    };}
    

    【讨论】:

    • 如果我错了,请纠正我,但您的函数返回的函数不是普通对象?
    • 这就是thunk 背后的概念。返回一个函数而不是返回 actiontype
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 2017-07-09
    • 2018-03-22
    • 2018-12-23
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 2019-12-18
    相关资源
    最近更新 更多