为什么会出现“操作必须是普通对象”错误?

时间:2018-09-22 02:01:16

标签: reactjs react-redux redux-thunk

我只是在学习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

2 个答案:

答案 0 :(得分:1)

您已兑现了承诺。一个Promise不是一个普通的对象,因此返回的动作将不是一个普通的对象,因此也不是错误。

由于您使用的是笨拙的中间件,因此您的操作可以是函数,而操作方法如下。

  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});
   });
};}

答案 1 :(得分: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>
);

containers / 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"));