redux中間件與異步操作

一腕铸、中間件的概念

如果要添加功能惜犀,只能在發(fā)送Action的時(shí)候才可以添加功能,即store.dispatch方法狠裹,所以舉一個(gè)官方的??要添加日志功能虽界,吧state和action都打印出來

let next = store.dispatch;
store.dispatch = function dispatchAndLog(action) {
  console.log('dispatching', action);
  next(action);
  console.log('next state', store.getState());
}

以上就是對dispatch的改造,也就是中間件的雛形
因此中間件就是一個(gè)函數(shù)涛菠,對store.dispatch函數(shù)進(jìn)行改造莉御,在發(fā)出action和執(zhí)行reducer之間,添加其他功能

二俗冻、中間件的用法

中間件都是現(xiàn)成的礁叔,所以我們只要知道如何使用中間件就好

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

const store = createStore(
  reducer,
  applyMiddleware(logger)
);

上面舉了一個(gè)logger中間件的??,redux-logger提供一個(gè)生成器createLogger迄薄,用來生成日志中間件logger琅关,然后將它放在applyMiddleware方法中傳入createstore中
注意
(1)createStore方法可以接受整個(gè)應(yīng)用的初始狀態(tài)作為參數(shù),那樣的話讥蔽,applyMiddleware就是第三個(gè)參數(shù)了涣易。

const store = createStore(
  reducer,
  initial_state,
  applyMiddleware(logger)
);

(2) applyMiddleware方法的三個(gè)參數(shù),就是三個(gè)中間件冶伞。有的中間件有次序要求新症,使用前要查一下文檔。比如碰缔,logger就一定要放在最后账劲,否則輸出結(jié)果會不正確。

const store = createStore(
  reducer,
  applyMiddleware(thunk, promise, logger)
);

三、redux-actions

createAction

原來創(chuàng)建action:const start = () => ({ type: 'START' })
現(xiàn)在創(chuàng)建action:import createAction from 'redux-actions'
const start = createAction('START')

handleActions

原來的寫法是需要switch或if來匹配

const todos = (state = defaultState, action) => {
    switch (action.type) {
      case 'ADD_TODO':
        return [
          ...state,
          {
            id: action.id,
            text: action.text,
            str: action.str,
            completed: false
          }
        ]
      case 'TOGGLE_TODO':
        return state.map(todo =>
          (todo.id === action.id)
            ? {...todo, completed: !todo.completed}
            : todo
        )
      default:
        return state
    }
  }

使用redux-actionsreducer操作state:

const todos  = handleActions({
    ADD_TODO: (state, action) => ({...state,{
            id: action.id,
            text: action.text,
            str: action.str,
            completed: false
          }}),
    TOGGLE_TODO: (state, action) => state.map(todo =>
          (todo.id === action.id)
            ? {...todo, completed: !todo.completed}
            : todo
        )
}, defaultState)

四瀑焦、異步處理action

官網(wǎng)一個(gè)??

import fetch from 'cross-fetch'

export const REQUEST_POSTS = 'REQUEST_POSTS'
function requestPosts(subreddit) {
  return {
    type: REQUEST_POSTS,
    subreddit
  }
}

export const RECEIVE_POSTS = 'RECEIVE_POSTS'
function receivePosts(subreddit, json) {
  return {
    type: RECEIVE_POSTS,
    subreddit,
    posts: json.data.children.map(child => child.data),
    receivedAt: Date.now()
  }
}

 export const INVALIDATE_SUBREDDIT = ‘INVALIDATE_SUBREDDIT’
 export function invalidateSubreddit(subreddit) {
   return {
     type: INVALIDATE_SUBREDDIT,
     subreddit
   }
 }

// 來看一下我們寫的第一個(gè) thunk action 創(chuàng)建函數(shù)腌且!
// 雖然內(nèi)部操作不同,你可以像其它 action 創(chuàng)建函數(shù) 一樣使用它:
// store.dispatch(fetchPosts('reactjs'))

export function fetchPosts(subreddit) {

  // Thunk middleware 知道如何處理函數(shù)榛瓮。
  // 這里把 dispatch 方法通過參數(shù)的形式傳給函數(shù)铺董,
  // 以此來讓它自己也能 dispatch action。

  return function (dispatch) {

    // 首次 dispatch:更新應(yīng)用的 state 來通知
    // API 請求發(fā)起了禀晓。

    dispatch(requestPosts(subreddit))

    // thunk middleware 調(diào)用的函數(shù)可以有返回值精续,
    // 它會被當(dāng)作 dispatch 方法的返回值傳遞。

    // 這個(gè)案例中粹懒,我們返回一個(gè)等待處理的 promise重付。
    // 這并不是 redux middleware 所必須的,但這對于我們而言很方便凫乖。

    return fetch(`http://www.subreddit.com/r/${subreddit}.json`)
      .then(
        response => response.json(),
        // 不要使用 catch确垫,因?yàn)闀东@
        // 在 dispatch 和渲染中出現(xiàn)的任何錯(cuò)誤,
        // 導(dǎo)致 'Unexpected batch number' 錯(cuò)誤帽芽。
        // https://github.com/facebook/react/issues/6895
         error => console.log('An error occurred.', error)
      )
      .then(json =>
        // 可以多次 dispatch删掀!
        // 這里,使用 API 請求結(jié)果來更新應(yīng)用的 state导街。

        dispatch(receivePosts(subreddit, json))
      )
  }
}

四披泪、redux-promise中間件

import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import reducer from './reducers';

const store = createStore(
reducer,
applyMiddleware(promiseMiddleware)
);

這個(gè)中間件使得接受一個(gè)promise對象作為參數(shù),這時(shí)搬瑰,Action Creator 有兩種寫法款票。寫法一,返回值是一個(gè) 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()
});
});

######寫法二:**action對象的payload屬性是一個(gè)promise對象**徽职,這需要從redux-actions模塊引入createAction方法

import { createAction } from 'redux-actions';

class AsyncApp extends Component {
componentDidMount() {
const { dispatch, selectedPost } = this.props
// 發(fā)出同步 Action
dispatch(requestPosts(selectedPost));
// 發(fā)出異步 Action
dispatch(createAction(
'FETCH_POSTS',
fetch(/some/API/${postTitle}.json)
.then(response => response.json())
));
}

dispatch方法發(fā)出的是異步action,只有等到異步操作結(jié)束佩厚,這個(gè)action才會實(shí)際發(fā)出,createAction的第二個(gè)參數(shù)必須是一個(gè)promise對象



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末说订,一起剝皮案震驚了整個(gè)濱河市抄瓦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌陶冷,老刑警劉巖钙姊,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異埂伦,居然都是意外死亡煞额,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膊毁,“玉大人胀莹,你說我怎么就攤上這事』槲拢” “怎么了描焰?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栅螟。 經(jīng)常有香客問我荆秦,道長,這世上最難降的妖魔是什么力图? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任步绸,我火速辦了婚禮,結(jié)果婚禮上吃媒,老公的妹妹穿的比我還像新娘瓤介。我一直安慰自己,他們只是感情好晓折,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布惑朦。 她就那樣靜靜地躺著,像睡著了一般漓概。 火紅的嫁衣襯著肌膚如雪漾月。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天胃珍,我揣著相機(jī)與錄音梁肿,去河邊找鬼。 笑死觅彰,一個(gè)胖子當(dāng)著我的面吹牛吩蔑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播填抬,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼烛芬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了飒责?” 一聲冷哼從身側(cè)響起赘娄,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宏蛉,沒想到半個(gè)月后遣臼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拾并,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年揍堰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹏浅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屏歹,死狀恐怖隐砸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情西采,我是刑警寧澤凰萨,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站械馆,受9級特大地震影響胖眷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霹崎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一珊搀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尾菇,春花似錦境析、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至默赂,卻和暖如春沛鸵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缆八。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工曲掰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奈辰。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓栏妖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親奖恰。 傳聞我的和親對象是個(gè)殘疾皇子吊趾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容