[英]How does redux-api-middleware add data to the store?
I am creating a universal react application with redux and react router. 我正在用redux和react router创建一个通用的react应用程序。 I have most of the application setup with server-side rendering and basic redux actions (modifying a Boolean in the store). 我的大多数应用程序设置都带有服务器端渲染和基本的redux操作(在商店中修改布尔值)。 Now I would like to make some api calls to get data for my app. 现在,我想进行一些api调用以获取我的应用程序的数据。
I thought it would be a good idea to use the redux-api-middleware but I can't get the data to add to the store. 我认为使用redux-api-middleware是一个好主意,但是我无法将数据添加到存储中。 I followed the documentation and created an action that looks like this. 我按照文档进行操作,并创建了一个类似于以下的操作。
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']
}
}
I run this action on a button click in my page. 我在页面上单击一个按钮时执行此操作。 I see the action get fired but nothing goes into the store. 我看到该动作被解雇了,但没有任何东西进入商店。 I even added some custom code for the SUCCESS
action and was able to console.log()
the response but still could not get the data into the store. 我什至为SUCCESS
操作添加了一些自定义代码,并且能够console.log()
响应,但是仍然无法将数据放入存储中。
Also I have added the middleware to the store in the same way the documentation says to. 另外,我已经按照文档说明的方式将中间件添加到了商店中。
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);
}
So far I have tried a bunch of different things with the action, like making the actions into exportable symbols and calling them in a reducer and trying to merge the data into the current state that comes from the payload
attribute in redux-api-middleware, but no luck. 到目前为止,我已经对该操作进行了很多尝试,例如将这些操作制作成可导出的符号并在化简器中调用它们,然后尝试将数据合并到来自redux-api-middleware中的payload
属性的当前状态,但没有运气。
I really have 2 questions 我真的有两个问题
Any help, explanation or constructive criticism on the matter is really appreciated, thanks. 非常感谢您对此事的任何帮助,解释或建设性批评。
As far as I can see, redux-api-middleware
provides a bunch of facilities for making an API call, dispatching success/failure actions, and possibly processing the response a bit. 据我所知, redux-api-middleware
提供了许多用于进行API调用,调度成功/失败操作以及可能稍微处理响应的工具。 However, how you handle those actions in your reducers is up to you. 但是,如何处理减速器中的这些动作取决于您自己。 So, if you ask the middleware to dispatch "MY_REQUEST_SUCCESS"
, you'd need to add a "MY_REQUEST_SUCCESS"
handler into your reducer logic, and update the state appropriately. 因此,如果您要求中间件调度"MY_REQUEST_SUCCESS"
,则需要在您的reducer逻辑中添加"MY_REQUEST_SUCCESS"
处理函数,并适当地更新状态。
Like markerikson said, the library only provides you with the tools, you still have to write reduceres to respond to the action. 就像markerikson所说的那样,该库只为您提供工具,您仍然必须编写reduceres来响应操作。 In my case I finally got data with the following reducer. 在我的情况下,我终于通过以下减速器获得了数据。
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;
}
}
I also had to export the symbols like this 我也不得不导出这样的符号
export const REQUEST = Symbol('REQUEST');
export const SUCCESS = Symbol('SUCCESS');
export const FAILURE = Symbol('FAILURE');
Awesome library that gives you all the tools you need to creat api requests with very little code. 很棒的库为您提供了用很少的代码创建api请求所需的所有工具。 Hope this helps someone who is confused about this like I was. 希望这可以帮助像我一样对此感到困惑的人。
redux-api-middleware
isn't meant to store data to the store (that's why you don't need to setup any reducers). redux-api-middleware
并不意味着将数据存储到商店(这就是为什么您不需要设置任何reducer的原因)。 I actually built a library redux-cached-api-middleware that acts as a thin layer on top of redux-api-middleware
and adds caching (can easily be used as a simple storing) capabilities. 我实际上构建了一个库redux-cached-api-middleware ,该库充当redux-api-middleware
之上的薄层,并添加了缓存(可以轻松地用作简单存储)功能。
Here's an example component: 这是一个示例组件:
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);
This work in cached manner, but you could easily pass custom shouldFetch
function, and you would always refetch from API: 这项工作以缓存方式进行,但是您可以轻松地传递自定义的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
},
})
);
},
})
);
And the setup is as follows (notice the api reducer, that actually handles storing responses to redux state): 设置如下(注意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)
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.