1. 程式人生 > >redux的簡單使用

redux的簡單使用

Redux

我從學react起,一共寫了三次react專案
第一次是學生選課系統,完全不知道生命週期的規律和順序,也不知道axios到底應該放在哪裡才能更好的請求到,檔案分工不明確,沒有體現元件化的優勢,各處state異常混亂,完全定位不到錯誤位置。
第二次是研究生雙選導師的系統,由於時間原因,很多的元件、方法都是堆積在一個js檔案中,單個檔案過於臃腫,且大部分方法都是上一次的方法照搬。優點是明確了各生命週期該乾的事情,且明白了當系統慢慢擴充套件,慢慢變大時,普通的state渲染介面的缺陷就會逐漸暴露而出,狀態管理幾乎是所有bug的根源之處:

一、排錯困難:當出現問題的時候,難以定位到錯誤位置,元件巢狀元件,不知道到底是傳進去的時候出現的錯誤,還是在子元件某一生命週期出現的錯誤。

二、過多巢狀的state,讓開發者對於資料邏輯的混亂無所適從。

redux就是為此而生的一種技術,它使用單一的state倉庫(store)來儲存資料,修改其中資料只能通過動作(action)來進行,拿出來的資料只能可讀不可修改,保證了開發者對資料的修改都在同一位置,不會出現各生命週期各有一堆請求資料的程式碼的情況。

第三次就是我現在正在寫的餐廳管理系統,新使用的技術就是redux,使用前覺得,怎麼會有這麼麻煩的東西?修改還要通過動作,還不如我直接setState呢,還只有一個倉庫來存state,我每個介面一個state不好嗎?但是使用後才會發現,Redux很像是一個矯正工具,讓你保證單項的資料流流入單一位置,再只從這個倉庫取出資料。redux中修改資料的程式碼就像下方我舉的例子

1 const action = changeHeadColor(index);
2 store.dispatch(action);
changeHeadColor這個方法返回一個物件,物件中一定有一個type屬性,這個屬性可以看作是方法名或者是鑰匙,當你想去倉庫中修改資料,你就需要這把鑰匙去開啟相應的門。
1 export const changeHeadColor = (index) => ({
2     type: CHANGE_HEAD_COLOR,
3     index
4 })

然後就是我們的倉庫了,這個檔案我們專門用來儲存state。所以我們修改state的方法很明確了,通過呼叫action(動作),找到對應的reducer(操作倉庫的方法),通過這個純函式來修改state,且只有這種方式才能改變state

const defaultState = {
    headActiveColorIndex: 0
};
export default (state = defaultState, action) => {
    let newState;
    switch (action.type) {
        case CHANGE_HEAD_COLOR:
            newState = JSON.parse(JSON.stringify(state));//深度拷貝
            newState.headActiveColorIndex = action.index;
            return newState;
    }
    return state;
}

接下來我就將需要建立的檔案初步給大家展示一下。大概需要的檔案是四個,外加一個使用的元件檔案。

store.js

// 記得安裝redux 和 redux-thunk(中介軟體,後面會講)
import { createStore, applyMiddleware, compose } from 'redux';
import reducer from './reducer'
import thunk from 'redux-thunk'

//增強函式 一步方法,執行兩個函式
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

//中介軟體 
const enhancer = composeEnhancers(applyMiddleware(thunk));

const store = createStore(
    reducer, /* preloadedState, */
    enhancer
);

export default store;

actionType.js

// 單獨拿出一個檔案用於定義action的typeheaction本身的名字,這樣做的意想不到的好處是,當你輸入type名錯了的時候,是會出現報錯的,而不寫這個檔案的話,reducer檔案判斷type處會以為你有這個變數,作為一個判斷條件一直放在那裡,並不會報錯。報錯有利於你處理BUG
// 改變頂部導航欄背景顏色
export const CHANGE_HEAD_COLOR = 'changeHeadColor';

actionCreators.js

 import { CHANGE_HEAD_COLOR} from './actionTypes'
 
 export const changeHeadColor = (index) => ({
     type: CHANGE_HEAD_COLOR,
     index
 })

reducer.js

import { CHANGE_HEAD_COLOR } from './actionTypes'

const defaultState = {
    headActiveColorIndex: 0,
    tableList: []
};

export default (state = defaultState, action) => {
    let newState;
    switch (action.type) {
        case CHANGE_HEAD_COLOR:
            newState = JSON.parse(JSON.stringify(state));//深度拷貝
            newState.headActiveColorIndex = action.index;
            return newState;
    }
    return state;
}

head.js => 元件檔案

import React, { Component } from 'react'
import store from '../store'
import { changeHeadColor } from '../store/actionCreators'


class Head extends Component {
    constructor(props) {
        super(props);
        this.state = store.getState()
        // 訂閱 發生改變就修改檢視
        store.subscribe(this.storeChange.bind(this));
    }
    componentDidMount() {
        const action = changeHeadColor(10)
        store.dispatch(action)
    }
    render() {
        let { headActiveColorIndex } = this.state;
        return (
            <div className="head">
                {headActiveColorIndex }
            </div>
            <div onClick={this.testFun.bind(this)}>測試</div>
        )
    }
    testFun(){
        const action = changeHeadColor(1000)
        store.dispatch(action)
    }
    storeChange() {
        this.setState(store.getState())
    }
}

export default Head        

檔案結構如下,大家使用的時候建議按照自己的路徑重打一下路徑,比如我這裡就是因為全放在了一個store資料夾下,所以store.js檔案改名成了index.js

 

 

 然後大家就可以嘗試使用redux做專案了,這裡再提醒一點,如果大家沒有認為或是沒有意識到自己的react專案的狀態管理混亂的話,redux是沒有必要使用的。

 

這裡引用阮一峰老師的文章的話:     

     "如果你不知道是否需要 Redux,那就是不需要它。"

 

今天就到這裡,鑑於篇幅的問題沒有辦法說得更多,如果有其他問題的話可以加我的qq或私信我或留下您的資訊,我看到了會盡我的能力給大家解答。希望大家的專案少出BUG!下次更新再見啦。