再學 Redux

redux核心概念

  1. components View react頁面
  2. Action 如果需要修改store的數(shù)據(jù)必須派發(fā)一個動作,它的參數(shù)接收一個對象,對象里面必須要有一個type屬性,表示動作的類型,第二個屬性是你傳入的值
  3. Reducer 它必須是一個純函數(shù),來處理store數(shù)據(jù)的變化,它接收兩個參數(shù) 一個是state 上一次的數(shù)據(jù), 一個是action . 特別注意的是 不能在這里面修改 state數(shù)據(jù)或者action數(shù)據(jù)
  4. Store 倉庫 存放state數(shù)據(jù) 它是鏈接action與reducer的橋梁 它的實例對象上有些方法,需要去記住它.
  • getState() 獲取當前倉庫的 state 數(shù)據(jù)

  • dispacth(action) 派發(fā)一個動作

  • subscribe(cb) 監(jiān)聽倉庫數(shù)據(jù)的變化,如果倉庫數(shù)據(jù)有變化,這個回調(diào)函數(shù)就會執(zhí)行

  • unsubscribe(cb) 取消監(jiān)聽 當倉庫的數(shù)據(jù)發(fā)生改變的時候 subscribe里面的回調(diào)函數(shù)會觸發(fā),重新返回一個函數(shù) 這個函數(shù)需要在 componentswillunmount() {}這個生命周期鉤子函數(shù)里面執(zhí)行,執(zhí)行之后就當組件銷毀的時候,componentswillunmount()生命周期鉤子函數(shù)會執(zhí)行里面的 回調(diào)函數(shù)也會執(zhí)行就取消訂閱了.

  1. ActionTypes
    動作類型常量
  • 如果動作類型是一個字符串的話.出現(xiàn)bug 會非常惡心.
  • 作用只是解決字符串寫錯之后,調(diào)試bug 非常困難的問題
  1. ActionsCreates
  • 動作生成器
  • 就是一個函數(shù)這個函數(shù)調(diào)用之后,返回一個動作的對象

7.安裝 redux

npm install -- save redux || yarn add redux

拆分主reducer, 每個模塊的狀態(tài)都在reducer里面,將每個模塊的狀態(tài)拆分出去,在主的reducer文件中進行引用, 這時就要使用 redux里面的combineReducers方法,這個方法

在 主reducer.js文件中 調(diào)用redux的combineReducers方法,返回一個reducer純函數(shù) 并且把它暴露出去

8. redux的中間件

可以阮一峰學習文檔參考鏈接
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html
中間件主要的作用就是幫助我們實現(xiàn)異步代碼
之前動作一旦被派發(fā),是直接到了 reducer 的純函數(shù)里面,加上中間件之后,動作派發(fā)之后,首先會經(jīng)過中間件來處理,處理之后再到reducer里面去

中間件實現(xiàn)的原理
就是對 store,dispacth 進行重寫
代碼如下:

var  next = store.dispacth()
對store 進行重寫
store.dispacth= (action)=>{
默認接收一個 action 對象
console.log("操作之前的數(shù)據(jù)",store.getState());
next(action);
console.log("操作之后的數(shù)據(jù)",store.getState())
}

  1. 使用第三方提供的redux-logger 中間件
    作用主要是在 控制臺 日志輸出的中間件
  • 安裝 yarn add redux-logger --save 或 npm i --save redux-logger
    在主倉庫中引入:
  • import logger from 'redux-logger'
    在主倉庫的createStore(),傳遞 redux 的 applyMiddleware 調(diào)用即可
    applyMiddleware 主要作用就是使用中間件,這個函數(shù)用中間件作為參數(shù)比如: logger thunk saga 一般的話, logger需要放在后面
    代碼如下:
import { createStore, applyMiddleware, compose } from "redux";

import reducer from "./reducer";
import logger from "redux-logger";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(logger)));

export default store;
  1. 使用第三方提供的redux-thunk中間件(讓Redux能夠?qū)崿F(xiàn)異步的代碼)
  • 安裝 yarn add redux-thunk --save
  • 默認store.dispacth()只能接受一個對象,如果使用了redux-thunk這個中間件 store.dispacth()能接受一個函數(shù)
  • 簡單demo如下寫在組件里面
派發(fā)一個異步動作
store.dispatch(() => {
這里寫一個異步的代碼
      var url = "http://localhost:9090/shuju";
      fetch(url)
        .then(response => response.json())
        .then(res => {
再派發(fā)一個普通的動作
          store.dispatch(initlist(res));
        });
    });
  • 需要將這個方法放在 actionCreate.js 里面
    因為在組件頁面中 使用 store.dispacth() 這個方法使用了thunk 之后,里面可以接受一個函數(shù)或者是對象,在這個store.dispacth()參數(shù)的函數(shù) 放到actionCreate.js 里面自定義各一個函數(shù)里面可以發(fā)起ajax網(wǎng)絡(luò)請求 actionCreate里面的函數(shù)經(jīng)過第三方中間件的處理主動接受的參數(shù)有 store里面的 dispacth,getState 這兩個方法,這樣就不需要在重新的引入 store了 可以直接在 dispacth()一個動作給reducer.js
    第一種方式組件里面的代碼:
直接派發(fā)一個動作,但是這個動作是在actionCreate里面寫
    使用方式1 store.dispatch(initTodoSync); 注意不能加括號 , thunk 會讓initTodoSync執(zhí)行
(加括號的話initTodoSync返回一個undefined 而 store.dispacth 不能接受一個undefined)

第一種方式actionCreate代碼如下:

export const initlist = list => {
  return {
    type: INIT_LIST,  // 主的reducer文件中根據(jù)這個動作的類型,把獲取到的數(shù)據(jù)給store
    list
  };
};
export const initTodoSync = (dispatch, getState) => {
  var url = "http://localhost:9090/shuju";
  fetch(url)
    .then(response => response.json())
    .then(res => {
      console.log(res, "獲取成功了嗎?");
      console.log(getState());
      dispatch(initlist(res)); // 調(diào)用重新初始化倉庫數(shù)據(jù)的函數(shù),把獲取的數(shù)據(jù)傳過去
    });
};

第二種方式組件里面的代碼:

store.dispatch(initTodoSync());  //加括號

第二種方式actionCreate代碼如下:

export const initlist = list => {
  return {
    type: INIT_LIST,
    list
  };
};

export const initTodoSync = () => {
  return (dispatch, getState) => {
    var url = "http://localhost:9090/shuju";
    fetch(url)
      .then(response => response.json())
      .then(res => {
        console.log(res, "獲取成功了嗎?");
        console.log(getState());
        dispatch(initlist(res));
      });
  };
};

redux-thunk 實現(xiàn)的原理:

var next = store.dispacth()
store.dispacth=(action)=>{
if(action && typeof action=== "function"){
//動作是個函數(shù),就會直接執(zhí)行這個動作,并且把兩個參數(shù)傳遞下去
action(state.getState,state.dispacth)
} else{
  next(action)
  }
}

redux-react

安裝: npm install react-redux || yarn add react-redux
UI組件與容器組件的概念
UI組件: 只是負責數(shù)據(jù)的渲染,不負責數(shù)據(jù)的操作. 不負責跟倉庫打交道,所有的數(shù)據(jù)都是通過props
容器組件: 不負責數(shù)據(jù)渲染, 負責數(shù)據(jù)的操作, 跟倉庫打交道 ,所有的數(shù)據(jù)都是通過倉庫

connect的詳解

connect 方法返回一個高階函數(shù),接收一個組件的參數(shù),生成一個新的組件
connect 方法接收兩個參數(shù) 第一個參數(shù)mapStateToprops (倉庫數(shù)據(jù)發(fā)生改變時,自動執(zhí)行,通過props屬性自動給到組件頁面) 第二個參數(shù)mapDispacthToProps
代碼簡單實現(xiàn)如下

import React, { Component } from "react";
import { connect } from "react-redux";

class Dashboard extends Component {
  state = {
    name: ""
  };
  render() {
    const { name } = this.props;
    return (
      <div>
        <h2>我的名字{name}</h2>
        <button onClick={onTodoClick}>修改我的名字</button>
      </div>
    );
  }
}

const mapStateToprops = state => {
  return {
    name: this.state.name
  };
};
const mapDispacthToprops = () => {
  return {
    onTodoClick: () => {
      dispatch({
        type: "SET_VISIBILITY_FILTER",
        name: this.state.name
      });
    }
  };
};
export default connect(
  mapStateToprops,
  mapDispacthToprops
)(Dashboard);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市呢蔫,隨后出現(xiàn)的幾起案子胰舆,更是在濱河造成了極大的恐慌拣展,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擎淤,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機街望,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弟跑,“玉大人灾前,你說我怎么就攤上這事∶霞” “怎么了哎甲?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長饲嗽。 經(jīng)常有香客問我炭玫,道長,這世上最難降的妖魔是什么貌虾? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任吞加,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘榴鼎。我一直安慰自己伯诬,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布巫财。 她就那樣靜靜地躺著盗似,像睡著了一般。 火紅的嫁衣襯著肌膚如雪平项。 梳的紋絲不亂的頭發(fā)上赫舒,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音闽瓢,去河邊找鬼接癌。 笑死,一個胖子當著我的面吹牛扣讼,可吹牛的內(nèi)容都是我干的缺猛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼椭符,長吁一口氣:“原來是場噩夢啊……” “哼荔燎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起销钝,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤有咨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蒸健,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體座享,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年似忧,在試婚紗的時候發(fā)現(xiàn)自己被綠了渣叛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡橡娄,死狀恐怖诗箍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挽唉,我是刑警寧澤滤祖,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瓶籽,受9級特大地震影響匠童,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜塑顺,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一汤求、第九天 我趴在偏房一處隱蔽的房頂上張望俏险。 院中可真熱鬧,春花似錦扬绪、人聲如沸竖独。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽莹痢。三九已至,卻和暖如春墓赴,著一層夾襖步出監(jiān)牢的瞬間竞膳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工诫硕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坦辟,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓章办,卻偏偏與公主長得像锉走,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子纲菌,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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