redux+react-redux+示例的快速上手體驗

本文主要記錄下本身在react道路上的爬坑過程 以及對於剛學習redux的同窗提供一些可供參考的例子。vue

以前用vue用了好久 vue的語法糖用起來是真的舒服 不過如今公司項目用的是react 只好默默的從vue轉到react 其實畢竟他們都是相似的框架, 雖然語法大不一樣, 可是有些地方的思想仍是很像的, 廢話很少說了,開始正文...
本文主要分爲兩個部分:redux和react-redux。 首先大概過一下redux的基礎部分:react

1.redux

要知道redux和react並無半毛錢的關係,redux甚至能夠和jq一塊兒用。 react-redux纔是react的用於便捷操做redux的第三方插件。因此呢,學習react-redux以前咱們要比較熟悉的瞭解redux的思想。本文比較直接,不來虛的,直接上代碼:
首先就很熟悉了
1 使用官方腳手架
create-react-app redux-demonpm

2 環境搭建好以後 繼續安裝redux
npm install redux --Sredux

進入到項目文件夾 把咱們用不到的全咔咔刪掉瀏覽器

在src/index.js裏引入redux並建立action reducer和store
src/index.js:app

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;
    }
}

//建立store
const store = createStore(reducer);

console.log(store.getState())


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

這裏大概解釋下每一個的意思:
action:行爲 它是一個對象 裏面必有type來指定其類型 這個類型能夠理解爲你要作什麼,reducer要根據action的type來返回不一樣的state 每一個項目有且能夠有多個action
reducer: 能夠理解爲一個專門處理state的工廠 給他一箇舊數據它會根據不一樣action.type返回新的數據 也就是:舊state + action = 新state 每一個項目有且能夠有多個reducer
store: store本質上是一個狀態樹,保存了全部對象的狀態。任何UI組件都能直接的從store訪問特定對象的狀態。每一個項目有且只能有一個store
腦子裏有了這些基本的概念後咱們就能夠把reducer放到createStore裏並建立好store了框架

能夠看到 代碼的最後咱們打印了store.getState() 這段代碼簡單理解就是打印下store裏的數據
由於咱們只是寫了action並無給它dispatch 因此reducer只會走默認的default 因此僅僅是返回state=tiger 那麼tiger就是咱們以前定義好的state
此時咱們npm start 在瀏覽器打開該demo f12打開控制檯 能夠看到打印的數據爲:10000
這裏咱們只是簡單的回顧下redux的基礎知識 並無在app.js裏面寫任何東西dom

好 能夠看到在上面咱們雖然定義了action 可是好像並無什麼用啊? 接下來咱們要作的事情就是讓它變化了。
剛纔僅僅是得到到初始的數據 這並非咱們想要的結果 在實際項目中咱們確定有不少的需求 不一樣需求對應不一樣功能 不一樣功能得到不一樣數據,因此接下來咱們要用到dispatch給它派發不一樣的action,上代碼:
src/index.js:ide

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;
    }
}

//建立store
const store = createStore(reducer);

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

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

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

能夠看到, 打印的數據變成了 11000 也就是說reducer根據dispatch派發的action的type,return了新的state。固然咱們也能夠派發store.dispatch(decrease) 那打印的結果就是 10000,緣由想必你們都知道。
其實咱們僅僅是多寫了store.dispatch(increase) 和 store.subscribe(() =>{}) 他們的每一個做用大概解釋下:
dispatch的做用就是告訴reducer 我給你action, 你要根據個人action.type返回新的state。 而後reducer就會根據action的type,返回新的state。
咱們給它dispatch了action,reducer也作出相應 最後也返回新的state 可是其實這時候console.log()不會打印新的數據 由於state雖然變化了 可是仍是打印store.getState()仍是原始的數據
這時候咱們就須要store.subscribe(() =>{})了 它的做用就是每當reducer返回新的數據 它就會自動更新頁面 把UI組件的state更新下 否則的話 雖然state變化了 頁面仍不會更新(雖然如今尚未其餘組件)學習

2.react-redux

好了, 這些就是基本的redux的知識。咱們不難發現,這樣其實挺麻煩的。你須要寫好多好多東西,並且咱們並無把reducer,action什麼的給分離出去,否則的話我還要往不少組件裏面傳不少東西。這對咱們實際開發是很不友好的。
因此, 這時候就十分迫切須要react-redux了。它的做用是幫助咱們操做redux。有了它咱們能夠很方便的寫redux。接下來上代碼:

首先安裝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>當月工資爲{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;
    }
}

//建立store
const store = createStore(reducer);

//須要渲染什麼數據
function mapStateToProps(state) {
    return {
        tiger: state
    }
}
//須要觸發什麼行爲
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')
)

咱們能夠看到,咱們僅僅對代碼進行了稍微的改造,在index.js裏面寫個APP組件以方便咱們觀察,APP組件裏面的button分別觸發不一樣的事件。
action啊 reducer啊 store啊 想必你們都已經瞭解過了 這裏再也不作過多介紹。咱們主要關注下哪裏有變化:
首先最明顯的是demo中引入react-redux的Provider和connect,它們很是重要!這裏先大概解釋下它們的做用:
Provider:它是react-redux 提供的一個 React 組件,做用是把state傳給它的全部子組件,也就是說 當你用Provider傳入數據後 ,下面的全部子組件均可以共享數據,十分的方便。
Provider的使用方法是:把Provider組件包裹在最外層的組件,如代碼所示,把整個APP組件給包裹住,而後在Provider裏面把store傳過去。注意:必定是在Provider中傳store,不能在APP組件中傳store。
connect:它是一個高階組件 所謂高階組件就是你給它傳入一個組件,它會給你返回新的加工後的組件,注重用法倒簡單,深究其原理就有點難度。這裏不作connect的深究,主要是學會它的用法,畢竟想要深究必須先會使用它。首先它有四個參數([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]),後面兩個參數能夠不寫,不寫的話它是有默認值的。咱們主要關注下前兩個參數mapStateToProps和mapDispatchToProps。
connect的使用方法是:把指定的state和指定的action與React組件鏈接起來,後面括號裏面寫UI組件名。

除此以外demo中還多出了mapStateToProps mapDispatchToProps 他們又有什麼做用呢?通俗一點講的話就是:
好比你在一個很深的UI組件裏 當你想要得到store的數據就很麻煩。mapStateToProps就是告訴store你須要哪一個state,須要什麼數據就直接在mapStateToProps中寫出來,而後store就會返回給你。同理,若是你想要dispatch派發一些行爲怎麼辦呢,mapDispatchToProps就是告訴store你要派發什麼行爲,須要派發什麼行爲就在mapDispatchToProps中寫出來,而後store就會把你想要派發的行爲告訴reducer,接下來你們都應該知道了 reducer就會根據舊的state和action返回新的state。

好了 , 這時候咱們npm start 打開瀏覽器看一下有什麼效果:
圖片描述

能夠看到頁面上已經有內容,多了一段文字和兩個按鈕,當咱們點擊會有什麼反應呢?
圖片描述
果不其然,當咱們點擊'升職加薪'按鈕時候 '當月工資'也相應的增長了。咱們捋一下整個事件流程:
1 點擊按鈕 2 觸發PayDecrease()方法 3 該方法派發相應action 4 reducer根據action的type響應獲得新的state 5 經過{this.props.tiger}拿到新的state 渲染到頁面

ok, 這個簡單的demo咱們就實現了。可是如今還有一個問題:咱們把全部的action reducer store Provider connect等等都寫在了一個頁面,這在咱們實際開發中確定是不合理的,因此,咱們最後就給這個小demo再優化下:
首先,咱們要把action,reducer什麼的抽離出去,做爲一個單獨的文件,而後再導出:
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組件寫在外面 (此處必定要注意: 導出的不是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>當月工資爲{this.props.tiger}</h2>
        <button onClick={PayIncrease}>升職加薪</button>
        <button onClick={PayDecrease}>遲到罰款</button>
      </div>
    );
  }
}
//須要渲染什麼數據
function mapStateToProps(state) {
  return {
    tiger: state
  }
}
//須要觸發什麼行爲
function mapDispatchToProps(dispatch) {
  return {
    PayIncrease: () => dispatch({ type: '漲工資' }),
    PayDecrease: () => dispatch({ type: '扣工資' })
  }
}

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

把這些東西分離出去以後,此時的index.js看起來明顯就簡潔了許多:
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'

//建立store
const store = createStore(reducer);


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

好了,比較基礎的redux和react-redux例子到這就結束了,感受廢話有點多了。。能看完的都是真愛。。 哪有錯誤 歡迎指正!

相關文章
相關標籤/搜索