15分鐘學(xué)會(huì)在React中使用Redux

React作為一套優(yōu)秀的前端框架,為我們提供了一套十分優(yōu)秀的頁面構(gòu)建方法和思想∏渫拢可是,React還只是一套視圖構(gòu)建框架锋华,在軟件設(shè)計(jì)模塊里面還只是MVC的View層嗡官,涉及數(shù)據(jù)模型時(shí)需要一些其他框架的輔助。其中毯焕,最著名的莫過于Redux了衍腥。既然是結(jié)合React使用Redux,那么前端大爺假設(shè)你已經(jīng)使用過React框架纳猫,對React有一定的了解了紧阔,并且大概知道action, reducer, dispatch的關(guān)系,否則請先移步其他書籍文檔续担,因?yàn)闊o論如何15分鐘內(nèi)不可能從不會(huì)走到學(xué)會(huì)跑。

-----------------------------------分割線 0 分鐘---------------------------------

先解釋原理

首先活孩,React組件有state, props沒錯(cuò)吧物遇。state是內(nèi)部的狀態(tài),props是父組件傳進(jìn)來的屬性,state, props變化了要觸發(fā)react diff并且調(diào)用render方法更新組件询兴,同意吧乃沙。好,就是這么簡單的react基本原理诗舰,告訴我們除了用戶交互導(dǎo)致內(nèi)部state變化外警儒,數(shù)據(jù)流是從父組件通過props流向子組件導(dǎo)致子組件更新。這就是React的單向數(shù)據(jù)流:

            自頂向下單向數(shù)據(jù)流眶根!
            
            自頂向下單向數(shù)據(jù)流蜀铲!
            
            自頂向下單向數(shù)據(jù)流!

重要的事情說三遍属百。

假設(shè)我們的app入口是這樣的:

ReactDOM.render(
    <App />
    document.getElementById('root')
);

這個(gè)App也是一個(gè)React組件记劝,它是我們的項(xiàng)目中居于最頂層的父組件。如果我們有某個(gè)組件族扰,他能夠提供數(shù)據(jù)源厌丑,而又居于App之上,那么數(shù)據(jù)就可以源源不斷的從它往下流到App以及各級子孫節(jié)點(diǎn)上去渔呵。所以Redux給我們提供了Provider:


import { Provider } from 'react-redux'


ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>, 
    document.getElementById('root')
);


-----------------------------------分割線 5 分鐘---------------------------------

Provider接受一個(gè)屬性store怒竿,這就是我們?nèi)值臄?shù)據(jù)store。我們要根據(jù)reducer函數(shù)來創(chuàng)建它扩氢。

import { createStore } from 'redux'
import { combineReducers } from 'redux'


//reducer函數(shù)接受兩個(gè)參數(shù)耕驰,state和action,state帶默認(rèn)的初始值
function reducer1(state = [], action) {
    switch(action.type) {
        case 'add':
            return [...state, 'apple is very delicious'];  // 這里一定要返回一個(gè)新的數(shù)組类茂,而不能寫成state.push('apple is very delicious1');
            
        default  :
            return state;  
    }
}

//reducer當(dāng)然可以定義多個(gè)耍属,不同的reducer對應(yīng)著不同的state對象,上面的reducer1操作一個(gè)數(shù)組對象巩检,這個(gè)reducer2操作一個(gè)Number類型state
function reducer2(state = 0, action) {
    switch(action.type) {
        case 'increase' :
            ++state;
            return state;
        default:
            return state;    
    }
}

const reducer = combineReducers({
    reducer1,
    reducer2
  })

var store = createStore(reducer);   

store生成了厚骗,隨時(shí)可以通過store.getState()獲得當(dāng)前store的值。初始狀態(tài)下調(diào)用getState()獲得的返回值是

{reducer1: [], reducer2: 0}兢哭。

看领舰,reducer函數(shù)的名字對應(yīng)著store里面state的名字。

為了幫助初學(xué)者學(xué)習(xí)迟螺,可以添加以下語句冲秽,監(jiān)聽每一次dispatch操作后store的狀態(tài):

store.subscribe(()=>{
    console.log(store.getState());
})

-----------------------------------分割線 10 分鐘---------------------------------

現(xiàn)在我們有了最高級別的Provider,并定義好了reducers, 傳入了store矩父。接下來我們該考慮子組件了锉桑。子組件長什么樣,要靠父組件給的props決定窍株,可是數(shù)據(jù)都在最高級別的provider store里面民轴,怎么樣把store里面的數(shù)據(jù)拿出來作為props給子組件呢9ツ!后裸?瑰钮?

react-redux給我們提供了魔法黑科技:mapStateToProps和mapDispatchToProps。

顧名思義微驶,把state和dispatch從store里面拿出來浪谴,作為props傳給子組件!

const mapStateToProps = state => {
  return {
    state1: state.reducer1
  }
}

const mapDispatchToProps = dispatch => {
  return {
    add: () => {
      dispatch({
        type:'add'
      })
    }
  }
}

class AppView extends Component {

  render() {
    const list = this.props.state1.map(v=>{
      return (<p className="App-intro">{v}</p>)
    })
    return (
      <div className="App">
        <p>{list.length}</p>
        {
          list
        }
        
        <button onClick={()=>this.props.add()}>add</button>
      </div>
    );
  }
}


const App = connect(
  mapStateToProps,
  mapDispatchToProps
)(AppView)
export default App;

看到了嗎因苹,經(jīng)過mapStateToProps和mapDispatchToProps處理后苟耻,我們直接在子組件AppView里面使用this.props.state1就可以拿到store里面的數(shù)據(jù),直接使用this.props.add就可以dispatch相應(yīng)的action容燕。store變化后視圖的更新是自動(dòng)的梁呈,無需手工干預(yù)。

源代碼見:https://github.com/myairforce1/simpleReduxDemo

看到這你是不是對在React中使用Redux有點(diǎn)感覺了呢蘸秘?請?jiān)彵疚氖褂昧艘粋€(gè)極為簡陋的例子官卡。本著老少咸宜,童叟無欺的初衷醋虏,我盡量搬上來一個(gè)功能少寻咒,但是好理解的例子。如果的確幫助到您颈嚼,請留下您對本文的喜愛毛秘。

-----------------------------------分割線 15 分鐘---------------------------------
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市阻课,隨后出現(xiàn)的幾起案子叫挟,更是在濱河造成了極大的恐慌,老刑警劉巖限煞,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抹恳,死亡現(xiàn)場離奇詭異,居然都是意外死亡署驻,警方通過查閱死者的電腦和手機(jī)奋献,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旺上,“玉大人瓶蚂,你說我怎么就攤上這事⌒ǎ” “怎么了窃这?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長征候。 經(jīng)常有香客問我钦听,道長洒试,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任朴上,我火速辦了婚禮,結(jié)果婚禮上卒煞,老公的妹妹穿的比我還像新娘痪宰。我一直安慰自己,他們只是感情好畔裕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布衣撬。 她就那樣靜靜地躺著,像睡著了一般扮饶。 火紅的嫁衣襯著肌膚如雪具练。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天甜无,我揣著相機(jī)與錄音扛点,去河邊找鬼。 笑死岂丘,一個(gè)胖子當(dāng)著我的面吹牛陵究,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奥帘,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铜邮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寨蹋?” 一聲冷哼從身側(cè)響起松蒜,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎已旧,沒想到半個(gè)月后秸苗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡评姨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年难述,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了深碱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侵状。...
    茶點(diǎn)故事閱讀 39,764評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖琼娘,靈堂內(nèi)的尸體忽然破棺而出嗦枢,到底是詐尸還是另有隱情攀芯,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布文虏,位于F島的核電站侣诺,受9級特大地震影響殖演,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜年鸳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一趴久、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧搔确,春花似錦彼棍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涕蜂,卻和暖如春华匾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背机隙。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工蜘拉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人黍瞧。 一個(gè)月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓诸尽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親印颤。 傳聞我的和親對象是個(gè)殘疾皇子您机,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評論 2 354

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