我正在尝试将Redux集成到我的React项目中.目前我没有使用任何Flux框架.
我的应用程序从API获取一些数据并以一种漂亮的方式显示它,如下所示:
componentDidMount() { getData(); } getData() { const self = this; ajax({ url: apiUrl, }) .success(function(data) { self.setState({ data: data, }); }) .error(function() { throw new Error('Server response failed.'); }); }
在阅读有关Redux的文章时,我已经确定了两种可行的方法,可用于处理在商店中存储我的成功数据:
使用异步中间件,或
ADD_DATA
从ajax函数的成功回调调度操作
但我不确定哪种方法更好.
回调中的调度操作听起来很容易实现和理解,而异步中间件更难以向不习惯使用函数式语言的人解释.
我个人更喜欢使用自定义中间件来实现这一目标.它使操作更容易遵循,并且具有更少的样板IMO.
我已经设置了我的中间件来查找从与某个签名匹配的操作返回的对象.如果找到此对象模式,则会专门处理它.
例如,我使用如下所示的操作:
export function fetchData() { return { types: [ FETCH_DATA, FETCH_DATA_SUCCESS, FETCH_DATA_FAILURE ], promise: api => api('foo/bar') } }
我的自定义中间件看到该对象有一个types
数组和一个promise
函数,并专门处理它.这是它的样子:
import 'whatwg-fetch'; function isRequest({ promise }) { return promise && typeof promise === 'function'; } function checkStatus(response) { if (response.status >= 200 && response.status < 300) { return response; } else { const error = new Error(response.statusText || response.status); error.response = response.json(); throw error; } } function parseJSON(response) { return response.json(); } function makeRequest(urlBase, { promise, types, ...rest }, next) { const [ REQUEST, SUCCESS, FAILURE ] = types; // Dispatch your request action so UI can showing loading indicator next({ ...rest, type: REQUEST }); const api = (url, params = {}) => { // fetch by default doesn't include the same-origin header. Add this by default. params.credentials = 'same-origin'; params.method = params.method || 'get'; params.headers = params.headers || {}; params.headers['Content-Type'] = 'application/json'; params.headers['Access-Control-Allow-Origin'] = '*'; return fetch(urlBase + url, params) .then(checkStatus) .then(parseJSON) .then(data => { // Dispatch your success action next({ ...rest, payload: data, type: SUCCESS }); }) .catch(error => { // Dispatch your failure action next({ ...rest, error, type: FAILURE }); }); }; // Because I'm using promise as a function, I create my own simple wrapper // around whatwg-fetch. Note in the action example above, I supply the url // and optionally the params and feed them directly into fetch. // The other benefit for this approach is that in my action above, I can do // var result = action.promise(api => api('foo/bar')) // result.then(() => { /* something happened */ }) // This allows me to be notified in my action when a result comes back. return promise(api); } // When setting up my apiMiddleware, I pass a base url for the service I am // using. Then my actions can just pass the route and I append it to the path export default function apiMiddleware(urlBase) { return function() { return next => action => isRequest(action) ? makeRequest(urlBase, action, next) : next(action); }; }
我个人喜欢这种方法,因为它集中了很多逻辑,并为您提供了api操作结构的标准实施.这样做的缺点是对那些不熟悉redux的人来说可能有些神奇.我也使用thunk中间件,这两者一起解决了我到目前为止的所有需求.