Redux学习总结二

参考阮一峰Redux教程
上一篇介绍了Redux的基本做法:用户发出Action,Reducer函数算出新的State,View重新渲染。
为实现Reducer的异步操作,就需要使用新的工具:中间件(middleware).
##一、中间件
只有发送Action的这个步骤即store.dispatch()方法,可以添加功能。

//添加日志功能
let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
  console.log('dispatching', action);
  next(action);
  console.log('next state', store.getState());
}

中间件就是一个函数,对store.dispatch方法进行改造,在发出Action和执行Reducer这两步之间,添加了其他功能。
##二、中间件的用法

import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();
const store = createStore(
  reducer,
  applyMiddleware(logger)
);

上面代码中,redux-logger提供一个生成器createLogger,可以生成中间件logger,然后将它放在applyMiddleware方法中,传入createStore方法,就完成了store.dispatch()的功能增强。

注:1.createStore方法可以接受整个应用的初始状态作为参数,这样applyMiddleware就是第三个参数。
2.中间件的次序有讲究
##三、applyMiddlewares()
applyMiddlewares()是Redux的原生方法,作用是将所有中间件组成一个数组,依次执行。

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer);
    var dispatch = store.dispatch;
    var chain = [];
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);
    return {...store, dispatch}
  }
}

上面代码中,所有中间件被放进了一个数组chain,然后嵌套执行,最后执行store.dispatch(),由此可知,中间件内部(middlewareAPI)可以拿到getState和dispatch这两个方法。
##四、异步操作的基本思路
异步操作要发出三种不同的Action

1. 操作发起时的Action
2. 操作成功时的Action
3. 操作失败时的Action

除了Action种类不同,异步操作的State也要进行改造,反映不同的操作状态。

let state = {
  // ... 
  isFetching: true,
  didInvalidate: true,
  lastUpdated: 'xxxxxxx'
};

因此,整个异步操作的思路为:
1. 操作开始时,送出一个Action,触发State更新为"正在操作"状态,View重新渲染;
2. 操作结束后,再送出一个Action,触发State更新为"操作结束"状态,View再一次重新渲染;
##五、redux-thunk中间件
系统自动发送第二个Action例子:

class AsyncApp extends Component {
  componentDidMount() {
    const { dispatch, selectedPost } = this.props
    dispatch(fetchPosts(selectedPost))
  }
// ...

注:加载成功后(componentDidMount方法),它发出了(dispatch方法)一个Action,向服务器要求数据fetchPosts(selectedSubreddit),这里fetchPosts就是Action Creator。

const fetchPosts = postTitle => (dispatch, getState) => {
  dispatch(requestPosts(postTitle));
  return fetch(`/some/API/${postTitle}.json`)
    .then(response => response.json())
    .then(json => dispatch(receivePosts(postTitle, json)));
  };
};
// 使用方法一
store.dispatch(fetchPosts('reactjs'));
// 使用方法二
store.dispatch(fetchPosts('reactjs')).then(() =>
  console.log(store.getState())
);

注:由于fetchPosts返回了一个函数,而普通的Action Creator默认返回一个对象,且普通Action Creator的参数是Action的内容。

因此,这就要使用中间件redux-thunk来改造store.dispatch,使得后者可以接受函数作为参数。

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducer from './reducers';
// Note: this API requires redux@>=3.1.0
const store = createStore(
  reducer,
  applyMiddleware(thunk)
);

##六、redux-promise中间件
另一种异步操作的解决方案就是让Action Creator返回一个Promise对象,这时就需要使用redux-promise中间件。

import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import reducer from './reducers';
const store = createStore(
  reducer,
  applyMiddleware(promiseMiddleware)
); 

这个中间件使得store.dispatch方法可以接受promise对象作为参数,这时Action Creator有两种写法。
1. 返回值为一个Promise对象

const fetchPosts = 
  (dispatch, postTitle) => new Promise(function (resolve, reject) {
     dispatch(requestPosts(postTitle));
     return fetch(`/some/API/${postTitle}.json`)
       .then(response => {
         type: 'FETCH_POSTS',
         payload: response.json()
       });
});

2. Action对象的payload属性为一个Promise对象,这需要从redux-actions模块引入createAction方法

import { createAction } from 'redux-actions';

class AsyncApp extends Component {
  componentDidMount() {
    const { dispatch, selectedPost } = this.props
    // 发出同步 Action
    dispatch(requestPosts(selectedPost));
    // 发出异步 Action
    dispatch(createAction(
      'FETCH_POSTS', 
      fetch(`/some/API/${postTitle}.json`)
        .then(response => response.json())
    ));
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值