redux+react-redux+示例的快速上手體驗(yàn)

redux+react-redux+示例的快速上手體驗(yàn)

reduxreact.js

本文主要記錄下自己在react道路上的爬坑過(guò)程 以及對(duì)于剛學(xué)習(xí)redux的同學(xué)提供一些可供參考的例子芭毙。

之前用vue用了很久 vue的語(yǔ)法糖用起來(lái)是真的舒服 不過(guò)現(xiàn)在公司項(xiàng)目用的是react 只好默默的從vue轉(zhuǎn)到react 其實(shí)畢竟他們都是類(lèi)似的框架昆禽, 雖然語(yǔ)法大不同桩了, 但是有些地方的思想還是很像的疙咸, 廢話(huà)不多說(shuō)了睹逃,開(kāi)始正文...
本文主要分為兩個(gè)部分:redux和react-redux机隙。 首先大概過(guò)一下redux的基礎(chǔ)部分:

1.redux

要知道redux和react并沒(méi)有半毛錢(qián)的關(guān)系智玻,redux甚至可以和jq一起用桐绒。 react-redux才是react的用于便捷操作redux的第三方插件夺脾。所以呢之拨,學(xué)習(xí)react-redux之前我們要比較熟悉的了解redux的思想。本文比較直接咧叭,不來(lái)虛的蚀乔,直接上代碼:
首先就很熟悉了
1 使用官方腳手架
create-react-app redux-demo

2 環(huán)境搭建好之后 繼續(xù)安裝redux
npm install redux --S

進(jìn)入到項(xiàng)目文件夾 把我們用不到的全咔咔刪掉

在src/index.js里引入redux并創(chuàng)建action reducer和store
src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { createStore } from 'redux' 

//這是redux的原始state
const tiger = 10000

//這是action
const increase = {
    type:'漲工資'
}
const decrease = {
    type:'扣工資'
}

//這是reducer
const reducer = (state = tiger, action) => {
    switch (action.type){
      case '漲工資': 
        return state += 100;
      case '扣工資': 
        return state -= 100;
      default: 
        return state;
    }
}

//創(chuàng)建store
const store = createStore(reducer);

console.log(store.getState())

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

這里大概解釋下每個(gè)的意思:
action:行為 它是一個(gè)對(duì)象 里面必有type來(lái)指定其類(lèi)型 這個(gè)類(lèi)型可以理解為你要做什么,reducer要根據(jù)action的type來(lái)返回不同的state 每個(gè)項(xiàng)目有且可以有多個(gè)action
reducer: 可以理解為一個(gè)專(zhuān)門(mén)處理state的工廠(chǎng) 給他一個(gè)舊數(shù)據(jù)它會(huì)根據(jù)不同action.type返回新的數(shù)據(jù) 也就是:舊state + action = 新state 每個(gè)項(xiàng)目有且可以有多個(gè)reducer
store: store本質(zhì)上是一個(gè)狀態(tài)樹(shù)菲茬,保存了所有對(duì)象的狀態(tài)吉挣。任何UI組件都能直接的從store訪(fǎng)問(wèn)特定對(duì)象的狀態(tài)。每個(gè)項(xiàng)目有且只能有一個(gè)store
腦子里有了這些基本的概念后我們就可以把reducer放到createStore里并創(chuàng)建好store了

可以看到 代碼的最后我們打印了store.getState() 這段代碼簡(jiǎn)單理解就是打印下store里的數(shù)據(jù)
因?yàn)槲覀冎皇菍?xiě)了action并沒(méi)有給它dispatch 所以reducer只會(huì)走默認(rèn)的default 所以?xún)H僅是返回state=tiger 那么tiger就是我們之前定義好的state
此時(shí)我們npm start 在瀏覽器打開(kāi)該demo f12打開(kāi)控制臺(tái) 可以看到打印的數(shù)據(jù)為:10000
這里我們只是簡(jiǎn)單的回顧下redux的基礎(chǔ)知識(shí) 并沒(méi)有在app.js里面寫(xiě)任何東西

好 可以看到在上面我們雖然定義了action 但是好像并沒(méi)有什么用巴竦睬魂? 接下來(lái)我們要做的事情就是讓它變化了。
剛才僅僅是獲得到初始的數(shù)據(jù) 這并不是我們想要的結(jié)果 在實(shí)際項(xiàng)目中我們肯定有很多的需求 不同需求對(duì)應(yīng)不同功能 不同功能獲得不同數(shù)據(jù)镀赌,所以接下來(lái)我們要用到dispatch給它派發(fā)不同的action氯哮,上代碼:
src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { createStore } from 'redux' 

const tiger = 10000

//這是action
const increase = {
    type:'漲工資'
}
const decrease = {
    type:'扣工資'
}
//這是reducer
const reducer = (state = tiger, action) => {
    switch (action.type){
      case '漲工資': 
        return state += 100;
      case '扣工資': 
        return state -= 100;
      default: 
        return state;
    }
}

//創(chuàng)建store
const store = createStore(reducer);

//訂閱事件
store.subscribe(() =>
  console.log(store.getState())
);

//派發(fā)事件
store.dispatch(increase)

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

可以看到, 打印的數(shù)據(jù)變成了 11000 也就是說(shuō)reducer根據(jù)dispatch派發(fā)的action的type商佛,return了新的state喉钢。當(dāng)然我們也可以派發(fā)store.dispatch(decrease) 那打印的結(jié)果就是 10000,原因想必大家都知道良姆。
其實(shí)我們僅僅是多寫(xiě)了store.dispatch(increase) 和 store.subscribe(() =>{}) 他們的每個(gè)作用大概解釋下:
dispatch的作用就是告訴reducer 我給你action, 你要根據(jù)我的action.type返回新的state出牧。 然后reducer就會(huì)根據(jù)action的type,返回新的state歇盼。
我們給它dispatch了action舔痕,reducer也做出相應(yīng) 最后也返回新的state 但是其實(shí)這時(shí)候console.log()不會(huì)打印新的數(shù)據(jù) 因?yàn)閟tate雖然變化了 但是還是打印store.getState()還是原始的數(shù)據(jù)
這時(shí)候我們就需要store.subscribe(() =>{})了 它的作用就是每當(dāng)reducer返回新的數(shù)據(jù) 它就會(huì)自動(dòng)更新頁(yè)面 把UI組件的state更新下 不然的話(huà) 雖然state變化了 頁(yè)面仍不會(huì)更新(雖然現(xiàn)在還沒(méi)有其他組件)

2.react-redux

好了, 這些就是基本的redux的知識(shí)豹缀。我們不難發(fā)現(xiàn)伯复,這樣其實(shí)挺麻煩的。你需要寫(xiě)好多好多東西邢笙,而且我們并沒(méi)有把reducer啸如,action什么的給分離出去,不然的話(huà)我還要往很多組件里面?zhèn)骱芏鄸|西氮惯。這對(duì)我們實(shí)際開(kāi)發(fā)是很不友好的叮雳。
所以, 這時(shí)候就十分迫切需要react-redux了妇汗。它的作用是幫助我們操作redux帘不。有了它我們可以很方便的寫(xiě)redux。接下來(lái)上代碼:

首先安裝react-redux:

   `npm install react-redux --S`

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider, connect } from 'react-redux';

class App extends Component {
    render() {
        const { PayIncrease, PayDecrease } = this.props;
        return (
            <div className="App">
                <div className="App">
                    <h2>當(dāng)月工資為{this.props.tiger}</h2>
                    <button onClick={PayIncrease}>升職加薪</button>
                    <button onClick={PayDecrease}>遲到罰款</button>
                </div>
            </div>
        );
    }
}

const tiger = 10000

//這是action
const increase = {
    type: '漲工資'
}
const decrease = {
    type: '扣工資'
}
//這是reducer
const reducer = (state = tiger, action) => {
    switch (action.type) {
        case '漲工資':
            return state += 100;
        case '扣工資':
            return state -= 100;
        default:
            return state;
    }
}

//創(chuàng)建store
const store = createStore(reducer);

//需要渲染什么數(shù)據(jù)
function mapStateToProps(state) {
    return {
        tiger: state
    }
}
//需要觸發(fā)什么行為
function mapDispatchToProps(dispatch) {
    return {
        PayIncrease: () => dispatch({ type: '漲工資' }),
        PayDecrease: () => dispatch({ type: '扣工資' })
    }
}

//連接組件
App = connect(mapStateToProps, mapDispatchToProps)(App)

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

我們可以看到杨箭,我們僅僅對(duì)代碼進(jìn)行了稍微的改造寞焙,在index.js里面寫(xiě)個(gè)APP組件以方便我們觀(guān)察,APP組件里面的button分別觸發(fā)不同的事件。
action啊 reducer啊 store啊 想必大家都已經(jīng)了解過(guò)了 這里不再做過(guò)多介紹捣郊。我們主要關(guān)注下哪里有變化:
首先最明顯的是demo中引入react-redux的Provider和connect辽狈,它們非常重要!這里先大概解釋下它們的作用:
Provider:它是react-redux 提供的一個(gè) React 組件呛牲,作用是把state傳給它的所有子組件刮萌,也就是說(shuō) 當(dāng)你用Provider傳入數(shù)據(jù)后 ,下面的所有子組件都可以共享數(shù)據(jù)娘扩,十分的方便着茸。
Provider的使用方法是:把Provider組件包裹在最外層的組件,如代碼所示畜侦,把整個(gè)APP組件給包裹住,然后在Provider里面把store傳過(guò)去躯保。注意:一定是在Provider中傳store旋膳,不能在A(yíng)PP組件中傳store。
connect:它是一個(gè)高階組件 所謂高階組件就是你給它傳入一個(gè)組件途事,它會(huì)給你返回新的加工后的組件验懊,注重用法倒簡(jiǎn)單,深究其原理就有點(diǎn)難度尸变。這里不做connect的深究义图,主要是學(xué)會(huì)它的用法,畢竟想要深究必須先會(huì)使用它召烂。首先它有四個(gè)參數(shù)([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])碱工,后面兩個(gè)參數(shù)可以不寫(xiě),不寫(xiě)的話(huà)它是有默認(rèn)值的奏夫。我們主要關(guān)注下前兩個(gè)參數(shù)mapStateToProps和mapDispatchToProps怕篷。
connect的使用方法是:把指定的state和指定的action與React組件連接起來(lái),后面括號(hào)里面寫(xiě)UI組件名酗昼。

除此之外demo中還多出了mapStateToProps mapDispatchToProps 他們又有什么作用呢廊谓?通俗一點(diǎn)講的話(huà)就是:
比如你在一個(gè)很深的UI組件里 當(dāng)你想要獲得store的數(shù)據(jù)就很麻煩。mapStateToProps就是告訴store你需要哪個(gè)state麻削,需要什么數(shù)據(jù)就直接在mapStateToProps中寫(xiě)出來(lái)蒸痹,然后store就會(huì)返回給你。同理呛哟,如果你想要dispatch派發(fā)一些行為怎么辦呢叠荠,mapDispatchToProps就是告訴store你要派發(fā)什么行為,需要派發(fā)什么行為就在mapDispatchToProps中寫(xiě)出來(lái)扫责,然后store就會(huì)把你想要派發(fā)的行為告訴reducer蝙叛,接下來(lái)大家都應(yīng)該知道了 reducer就會(huì)根據(jù)舊的state和action返回新的state。

好了 公给, 這時(shí)候我們npm start 打開(kāi)瀏覽器看一下有什么效果:
[圖片上傳失敗...(image-ce0bae-1576896111419)]

可以看到頁(yè)面上已經(jīng)有內(nèi)容借帘,多了一段文字和兩個(gè)按鈕蜘渣,當(dāng)我們點(diǎn)擊會(huì)有什么反應(yīng)呢?
[圖片上傳失敗...(image-7cedb5-1576896111419)]
果不其然肺然,當(dāng)我們點(diǎn)擊'升職加薪'按鈕時(shí)候 '當(dāng)月工資'也相應(yīng)的增加了蔫缸。我們捋一下整個(gè)事件流程:
1 點(diǎn)擊按鈕 2 觸發(fā)PayDecrease()方法 3 該方法派發(fā)相應(yīng)action 4 reducer根據(jù)action的type響應(yīng)得到新的state 5 通過(guò){this.props.tiger}拿到新的state 渲染到頁(yè)面

ok, 這個(gè)簡(jiǎn)單的demo我們就實(shí)現(xiàn)了际起。但是現(xiàn)在還有一個(gè)問(wèn)題:我們把所有的action reducer store Provider connect等等都寫(xiě)在了一個(gè)頁(yè)面拾碌,這在我們實(shí)際開(kāi)發(fā)中肯定是不合理的,所以街望,我們最后就給這個(gè)小demo再優(yōu)化下:
首先校翔,我們要把a(bǔ)ction,reducer什么的抽離出去灾前,作為一個(gè)單獨(dú)的文件防症,然后再導(dǎo)出:
src/index.reducer.js:

const tiger = 10000

//這是action
const increase = {
    type: '漲工資'
}
const decrease = {
    type: '扣工資'
}
//這是reducer
const reducer = (state = tiger, action) => {
    switch (action.type) {
        case '漲工資':
            return state += 100;
        case '扣工資':
            return state -= 100;
        default:
            return state;
    }
}
export default reducer

其次,我們也要把APP組件寫(xiě)在外面 (此處一定要注意: 導(dǎo)出的不是APP組件哎甲,而是connect后的APP組件)
src/APP.js:

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

class App extends Component {

  componentDidMount() {
    console.log(this.props)
  } 
  render() {
    const { PayIncrease, PayDecrease } = this.props;
    return (
      <div className="App">
        <h2>當(dāng)月工資為{this.props.tiger}</h2>
        <button onClick={PayIncrease}>升職加薪</button>
        <button onClick={PayDecrease}>遲到罰款</button>
      </div>
    );
  }
}
//需要渲染什么數(shù)據(jù)
function mapStateToProps(state) {
  return {
    tiger: state
  }
}
//需要觸發(fā)什么行為
function mapDispatchToProps(dispatch) {
  return {
    PayIncrease: () => dispatch({ type: '漲工資' }),
    PayDecrease: () => dispatch({ type: '扣工資' })
  }
}

export default App = connect(mapStateToProps, mapDispatchToProps)(App)

把這些東西分離出去之后蔫敲,此時(shí)的index.js看起來(lái)明顯就簡(jiǎn)潔了許多:
src/index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import reducer from './index.reducer'

//創(chuàng)建store
const store = createStore(reducer);

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

好了,比較基礎(chǔ)的redux和react-redux例子到這就結(jié)束了炭玫,感覺(jué)廢話(huà)有點(diǎn)多了奈嘿。。能看完的都是真愛(ài)吞加。裙犹。 哪有錯(cuò)誤 歡迎指正!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衔憨,一起剝皮案震驚了整個(gè)濱河市伯诬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巫财,老刑警劉巖盗似,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異平项,居然都是意外死亡赫舒,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)闽瓢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)接癌,“玉大人,你說(shuō)我怎么就攤上這事扣讼∪泵停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)荔燎。 經(jīng)常有香客問(wèn)我耻姥,道長(zhǎng),這世上最難降的妖魔是什么有咨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任琐簇,我火速辦了婚禮,結(jié)果婚禮上座享,老公的妹妹穿的比我還像新娘婉商。我一直安慰自己,他們只是感情好渣叛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布丈秩。 她就那樣靜靜地躺著,像睡著了一般淳衙。 火紅的嫁衣襯著肌膚如雪蘑秽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天滤祖,我揣著相機(jī)與錄音筷狼,去河邊找鬼瓶籽。 笑死匠童,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的塑顺。 我是一名探鬼主播汤求,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼严拒!你這毒婦竟也來(lái)了扬绪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤裤唠,失蹤者是張志新(化名)和其女友劉穎挤牛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體种蘸,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡墓赴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了航瞭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诫硕。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖刊侯,靈堂內(nèi)的尸體忽然破棺而出章办,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布藕届,位于F島的核電站挪蹭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏翰舌。R本人自食惡果不足惜嚣潜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望椅贱。 院中可真熱鬧懂算,春花似錦、人聲如沸庇麦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)山橄。三九已至垮媒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間航棱,已是汗流浹背睡雇。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饮醇,地道東北人它抱。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像朴艰,于是被迫代替她去往敵國(guó)和親观蓄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348