手拉手學React:Redux

redux中文網(wǎng)

何為Redux

Redux 是 JavaScript 狀態(tài)容器楣号,用來存儲項目中一些公共的數(shù)據(jù)救斑,做到數(shù)據(jù)“一處存儲羹蚣,多處取出”的事情袁翁,跟 Vue 的 Vuex 屬于一類角色蜈七。

它的誕生是為了解決用 React 開發(fā)大型項目中解決不了難題秒拔。如果你的項目中組件繁多,而且組件之間的通信又必不可少飒硅,這個時候 Redux 能很好的解決這個問題砂缩。

舉個例子,原本組件通信是只有父子通信三娩,如果爺孫倆通信就需要借助“父”來實現(xiàn):

沒有Redux時的組件通信

問題就在于庵芭,如果組件非常多,數(shù)以千計雀监,再通信性能就非常低双吆,而且也不方便。那這個時候会前,把大家都需要的數(shù)據(jù)放在一個公共的地方好乐,誰要誰就去取:

有Redux的通信

這樣瓦宜,不管有多少個組件蔚万、組件的層次有多深,都能快速的拿到需要拿的數(shù)據(jù)临庇。

Redux 工作流程

開篇一張圖反璃,內(nèi)容全靠編:

image

Store 就相當于一個房地產(chǎn)中介一樣,我們想要一個地區(qū)的所有房源信息假夺,就需要通過它來獲取淮蜈,Reducers 是幕后人,中介的信息來源都是Reducers告訴它的侄泽,比喻成一個“房產(chǎn)資源手冊”可能更合適。

中介給了用戶三個行為:

  • getState()普通用戶級別專門獲取房源信息的唯一行為蜻韭。
  • dispatch(action)房東用戶級別通知中介悼尾,改變自家房源信息(state)的唯一行為柿扣。
  • subscribe()普通用戶級別如果相中了一套房子,并且告訴中介:“我對你這的房源信息比較感興趣闺魏,你這房源有啥新動向第一時間告訴我一下”未状,這樣就能第一時間收到房源信息(state)改變的消息。

介紹完這些之后析桥,咱們把整個流程串一下:

  • 普通用戶(React Components):通過getState()這一行為向中介(store)拿(注意是司草,不是拿到)最新的房源信息,中介接受到消息后泡仗,再通過房產(chǎn)資源手冊(Reducers)拿到最新的房源信息并反饋給用戶埋虹。所以,用戶最終的信息來源是通過Reducers獲取到的娩怎。
  • 房東用戶(React Components):通過dispatch(action)這一行為向中介發(fā)出信息搔课,說:“我要修改我家房源的一些信息,你幫我弄一下”截亦,其中爬泥,action.type是必不可少的,這是告訴中介自己房源的標識崩瓤。然后袍啡,中介再把這些信息傳給房產(chǎn)資源手冊Reducers,然后在手冊上對應的位置(該位置通過action.type找到)把對應的數(shù)據(jù)更改了却桶,最后中介通知已經(jīng)訂閱的用戶房源已經(jīng)更改了(subscribe())境输。這個角色擁有兩種身份:普通用戶房東用戶,它既能通過dispatch()修改自己發(fā)布到中介store上的房源信息肾扰,也能像普通用戶一樣訂閱畴嘶、獲取房源的一切信息。在我這里集晚,一個組件調(diào)用了dispatch()就視為房東用戶窗悯,否則就是普通用戶

這中間也有一些限制偷拔,比如action必須擁有type字段蒋院,其他屬性可能由用戶自定義,reducer是一個純函數(shù)莲绰,應當遵循純函數(shù)的一些設(shè)計理念欺旧。

不得改寫參數(shù)。
不能有異步操作蛤签。
不能調(diào)用Date.now()或者Math.random()等不純的方法辞友,因為每次會得到不一樣的結(jié)果。(引用自阮一峰

雇傭中介,自當用戶

現(xiàn)在咱們用代碼完成以上所述称龙,第一步是需要有中介(store)留拾,才會有用戶,所以先創(chuàng)建中介(store):

import { createStore } from 'redux';
import reducer from './reducer'; // 同時把房產(chǎn)資源手冊(reducer)交給中介

const store = createStore(reducer);

export default store;
/**
 * 每次用戶手動調(diào)用dispatch的時候鲫尊,會自動調(diào)用這個方法
 *
 * <strong>這個方法只能接受state痴柔,絕不能修改state,這是明文限制疫向!</strong>
 * @param {Object} state 上一個未改變的state
 * @param {Object} action 當前用戶傳遞過來的action
 * @param {String} action.type action的類型咳蔚,通過這個類型,得知用戶需要改動哪個變量
 * @return {{inputValue: string, list: Array}}
 */
export default function (state = defaultState, action) {
    const newState = JSON.parse(JSON.stringify(state));
    if (action.type === 'CHANGE_INPUT_VALUE') {
        /** @namespace action.value */
        newState.inputValue = action.value;
    } else if (action.type === 'LIST_ADD') {
        newState.list.push(newState.inputValue);
        newState.inputValue = '';
    }
    return newState;
}

先不看房產(chǎn)資源手冊(reducer)做了什么事情搔驼,第二步就是建立自己的用戶(React Components):

import React, { Component } from 'react';
import 'antd/dist/antd.css';
import { Input, Button, List } from 'antd';
import store from '../store'; // 第一步:引入中介(store)

class Home extends Component {
    constructor(...args) {
        super(...args);
        this.state = store.getState(); // 第二步:得到全部房源信息
        store.subscribe(() => { // 第三步:這個用戶(React components)需要第一時間知道房源的最新動向
            this.setState(store.getState());
        }); // 訂閱store谈火,store數(shù)據(jù)發(fā)生改變的時候需要做的事情,這個方法同時會返回一個方法匙奴,用來取消訂閱
    }
    inputChange = (e) => {
        const action = {
            type: 'CHANGE_INPUT_VALUE',
            value: e.target.value
        };
        store.dispatch(action);
    };
    btnSubmit = () => {
        store.dispatch({
            type: 'LIST_ADD'
        }) // 第四步:升級為房東堆巧,通知中介(store)修改自己的房源信息,這里對應房產(chǎn)資源手冊的代碼邏輯
    };
    render() {
        return (
            <div style={{ margin: '10px' }}>
                <Input
                    value={this.state.inputValue}
                    placeholder="Basic usage"
                    style={{ width: '300px' }}
                    onChange={this.inputChange}
                />
                <Button type="primary" style={{ marginLeft: '10px' }} onClick={this.btnSubmit}>提交</Button>
                <List
                    style={{ marginTop: '10px', width: '300px' }}
                    bordered
                    dataSource={this.state.list}
                    renderItem={item => (<List.Item>{item}</List.Item>)}
                />
            </div>
        );
    }
}

export default Home;

代碼優(yōu)化

需要將上面action.type值單獨提出來放在一個常量文件里泼菌,組件中和reducer里就更不容易出錯谍肤。

統(tǒng)一創(chuàng)建action

// actionCreateor.js
const defaultField = 'value'; // action默認的擴展字段
/**
 * 統(tǒng)一創(chuàng)建action
 * @param {String} type 類型
 * @param {any} value 值
 */
export function createAction(type, value) {
    if (!type) throw new Error('【非法參數(shù)】type必須是一個合法的參數(shù)值,當前type值是:' + type);
    let action = { type };
    switch (typeof value) {
        case 'object': {
            action = Object.assign(action, value);
            break;
        }
        default: {
            action[defaultField] = value;
        }
    }
    return action;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哗伯,一起剝皮案震驚了整個濱河市荒揣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌焊刹,老刑警劉巖系任,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異虐块,居然都是意外死亡俩滥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門贺奠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霜旧,“玉大人,你說我怎么就攤上這事儡率」揖荩” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵儿普,是天一觀的道長崎逃。 經(jīng)常有香客問我,道長眉孩,這世上最難降的妖魔是什么个绍? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任勒葱,我火速辦了婚禮,結(jié)果婚禮上巴柿,老公的妹妹穿的比我還像新娘错森。我一直安慰自己,他們只是感情好篮洁,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著殃姓,像睡著了一般袁波。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蜗侈,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天篷牌,我揣著相機與錄音,去河邊找鬼踏幻。 笑死枷颊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的该面。 我是一名探鬼主播夭苗,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼隔缀!你這毒婦竟也來了题造?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤猾瘸,失蹤者是張志新(化名)和其女友劉穎界赔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牵触,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡淮悼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了揽思。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袜腥。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绰更,靈堂內(nèi)的尸體忽然破棺而出瞧挤,到底是詐尸還是另有隱情,我是刑警寧澤儡湾,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布特恬,位于F島的核電站,受9級特大地震影響徐钠,放射性物質(zhì)發(fā)生泄漏癌刽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望显拜。 院中可真熱鬧衡奥,春花似錦、人聲如沸远荠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽譬淳。三九已至档址,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間邻梆,已是汗流浹背守伸。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留浦妄,地道東北人尼摹。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像剂娄,于是被迫代替她去往敵國和親蠢涝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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