0

背景

我正在使用 redux 和 react 路由器创建一个通用的反应应用程序。我的大部分应用程序设置都带有服务器端渲染和基本的 redux 操作(在商店中修改布尔值)。现在我想进行一些 api 调用来获取我的应用程序的数据。

当前实施

我认为使用 redux-api-middleware 是个好主意,但我无法将数据添加到商店。我按照文档创建了一个看起来像这样的操作。

示例-action.js

import { CALL_API } from `redux-api-middleware`;


export function fn_get_data () {
  [CALL_API]: {
    endpoint: 'http://www.example.com/api/users',
    method: 'GET',
    types: ['REQUEST', 'SUCCESS', 'FAILURE']
  }
}

我在我的页面中单击按钮运行此操作。我看到动作被触发,但没有任何东西进入商店。我什至为该SUCCESS操作添加了一些自定义代码,并且能够做出console.log()响应,但仍然无法将数据放入存储中。

此外,我还以与文档所述相同的方式将中间件添加到存储中。

configureStore.js

import { createStore, applyMiddleware, combineReducers } from 'redux';
import { apiMiddleware } from 'redux-api-middleware';
import reducers from './reducers';

const reducer = combineReducers(reducers);
const createStoreWithMiddleware = applyMiddleware(apiMiddleware)(createStore);

export default function configureStore(initialState) {
  return createStoreWithMiddleware(reducer, initialState);
}

到目前为止尝试过

到目前为止,我已经尝试了一系列不同的操作,比如将操作变成可导出的符号并在 reducer 中调用它们,并尝试将数据合并到来自payloadredux-api-middleware 中的属性的当前状态,但是没运气。

问题

我真的有2个问题

  • 为什么文档中没有减速器,这只是被忽略了还是响应中的数据直接进入了商店?
  • 为什么我调用的数据没有添加到存储中(我缺少什么)?

非常感谢您对此事的任何帮助、解释或建设性批评,谢谢。

4

3 回答 3

2

据我所知,redux-api-middleware它提供了一系列用于进行 API 调用、调度成功/失败操作以及可能处理响应的工具。但是,如何在 reducer 中处理这些操作取决于您自己。因此,如果您要求中间件 dispatch "MY_REQUEST_SUCCESS",您需要在"MY_REQUEST_SUCCESS"reducer 逻辑中添加一个处理程序,并适当地更新状态。

于 2016-11-03T21:18:25.187 回答
2

解决方案

就像markerikson 说的,这个库只为你提供了工具,你仍然需要编写reduceres 来响应动作。就我而言,我终于使用以下减速器获得了数据。

示例-reducer.js

import * as ExampleActionType from "../action/example-action";
import Immutable from "immutable";

let defaultState = Immutable.fromJS({
  fakeData: {}
});

function exampleState (state = defaultState, action) {
  switch (action.type) {

    case ExampleActionType.REQUEST : {
        console.log(action);
        return state;
    }

    case ExampleActionType.SUCCESS : {
        console.log(action);
        return state.merge({fakeData: action.payload });
    }

    case ExampleActionType.FAILURE : {
        console.log(action);
        return state;
    }

    default:
        return state;
  }
}

我还必须像这样导出符号

示例-action.js

export const REQUEST = Symbol('REQUEST');
export const SUCCESS = Symbol('SUCCESS');
export const FAILURE = Symbol('FAILURE');

结论

很棒的库,它为您提供了用很少的代码创建 api 请求所需的所有工具。希望这可以帮助像我一样对此感到困惑的人。

于 2016-11-04T09:14:24.933 回答
0

redux-api-middleware并不意味着将数据存储到商店(这就是您不需要设置任何减速器的原因)。我实际上构建了一个库redux-cached-api-middleware,它充当了一个薄层,redux-api-middleware并添加了缓存(可以很容易地用作简单的存储)功能。

这是一个示例组件:

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import api from 'redux-cached-api-middleware';
import Items from './Items';
import Error from './Error';

class ExampleApp extends React.Component {
  componentDidMount() {
    this.props.fetchData();
  }

  render() {
    const { result } = this.props;
    if (!result) return null;
    if (result.fetching) return <div>Loading...</div>;
    if (result.error) return <Error data={result.errorPayload} />;
    if (result.successPayload) return <Items data={result.successPayload} />;
    return <div>No items</div>;
  }
}

ExampleApp.propTypes = {
  fetchData: PropTypes.func.isRequired,
  result: PropTypes.shape({}),
};

const CACHE_KEY = 'GET/items';

const enhance = connect(
  state => ({
    result: api.selectors.getResult(state, CACHE_KEY),
  }),
  dispatch => ({
    fetchData() {
      return dispatch(
        api.actions.invoke({
          method: 'GET',
          headers: { Accept: 'application/json' },
          endpoint: 'https://my-api.com/items/',
          cache: {
            key: CACHE_KEY,
            strategy: api.cache
              .get(api.constants.CACHE_TYPES.TTL_SUCCESS)
              .buildStrategy({ ttl: 10 * 60 * 1000 }), // 10 minutes
          },
        })
      );
    },
  })
);

export default enhance(ExampleApp);

这以缓存的方式工作,但您可以轻松地传递自定义shouldFetch函数,并且您总是会从 API 重新获取:

const enhance = connect(
  state => ({
    result: api.selectors.getResult(state, CACHE_KEY),
  }),
  dispatch => ({
    fetchData() {
      return dispatch(
        api.actions.invoke({
          method: 'GET',
          headers: { Accept: 'application/json' },
          endpoint: 'https://my-api.com/items/',
          cache: {
            key: CACHE_KEY,
            shouldFetch: () => true
          },
        })
      );
    },
  })
);

设置如下(注意 api reducer,它实际上处理存储对 redux 状态的响应):

import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { apiMiddleware } from 'redux-api-middleware';
import api from 'redux-cached-api-middleware';
import reducers from './reducers';

const store = createStore(
  combineReducers({
    ...reducers,
    [api.constants.NAME]: api.reducer,
  }),
  applyMiddleware(thunk, apiMiddleware)
);
于 2018-08-10T17:12:46.983 回答