react-redux(一)

Redux著眼于對狀態(tài)整理的維護(hù)餐蔬,而不會產(chǎn)生出具體變動的部分缔莲。React是一個由狀態(tài)整體輸出界面的view層實現(xiàn)骡技,因此二者可以說是絕配钾菊。

如何在React項目中使用Redux


當(dāng)我們在說如何使用Redux時溃槐,說的其實是如何獲取并使用store內(nèi)容(狀態(tài)數(shù)據(jù))匣砖,以及創(chuàng)建并觸發(fā)action的過程。

一. 獲取并使用store


  • 屬性傳遞store狀態(tài)數(shù)據(jù)
    Redux的特點是整個應(yīng)用的狀態(tài)信息保存在一個store中昏滴,因而需要由store將數(shù)據(jù)從React組件樹節(jié)點傳入猴鲫。為了在數(shù)據(jù)變化時更新界面,還需要對store進(jìn)行監(jiān)聽:
function render() {
    const state = store.getState();
    React.render(
      <App state={state}/>,
      document.getElementById('app')
    );
}

store.subscribe(render);
render();

這樣谣殊,在組件App中拂共,可以通過this.props.state獲取狀態(tài)信息。組件App可以進(jìn)一步將狀態(tài)信息以props的形式傳遞給其子孫節(jié)點:

class App extends React.Component {
    render() {
        return (
          <Header content={this.props.title}/>
        );
    }
}

正如例子中的組件Header姻几,每個組件都可以從上層節(jié)點獲取它所需的信息宜狐。
然而势告,當(dāng)項目規(guī)模變大,組件層級變多時抚恒,情況會急劇惡化咱台,因為如果某個組件處在組件數(shù)第n級,那么沒修改一個屬性或增加一個組件俭驮,都需要改動n-1處回溺,這是無法想象的維護(hù)成本。
下面是很自然思考到的解決這個問題的辦法

  • 組件自行獲取store狀態(tài)數(shù)據(jù)

對應(yīng)的的做法是混萝,把createStore的結(jié)果通過一個獨立的模塊以module export的方式暴露出來遗遵,所有組件都可以直接去import這個模塊得到store,然后對store進(jìn)行subscribe:

// store.js
import reducers from 'reducers';
export default createStore(reducers);
// TodoFilter.js
import store from 'store';
export default class TodoFilter extends React.Component {
    constructor() {
        super();
        this.state = {
            filter: null
        };
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({
                filter: store.getState().filter
            });
        });
    }
    render() {
        // 界面渲染
    }
}

在組件掛載完成后監(jiān)聽store的變化逸嘀,取出最新狀態(tài)數(shù)據(jù)车要,并通過組件自身的setState方法更新組件的state信息,自動觸發(fā)重新渲染組件界面崭倘。
通過這種方式翼岁,我們順利地解決了前面遇到的問題,但依然存在一些問題:

  1. 組件私自與store建立聯(lián)系绳姨,致數(shù)據(jù)流難以追溯登澜。
  2. 擁有內(nèi)部state的組件不便于測試阔挠。
  3. 每個需要訪問store組件都實現(xiàn)一份subscript&setState這樣的邏輯略顯繁瑣飘庄。

react-redux將是上面這些問題較為成熟的、通用的解決方案购撼。

二. 創(chuàng)建與觸發(fā)action


在Flux架構(gòu)中跪削,store的狀態(tài)改變必須由action引起,除了獲取與使用store狀態(tài)數(shù)據(jù)外迂求,另外一個與store打交道的方式便是創(chuàng)建與觸發(fā)action碾盐。在Redux中,這個過程包含兩個部分:

  1. 創(chuàng)建action揩局,使用actionCreator
  2. 觸發(fā)action毫玖,通過store.dispatch將action作用到特定的store上

不難發(fā)現(xiàn)脱吱,觸發(fā)action的方法dispatch村斟,也面臨著一樣的問題,就是獲取store狗热。下面介紹針對這一問題的官方答案:react-redux驰怎。

react-redux


react-redux是Redux官方提供的React綁定阐滩,用于輔助在React項目中使用Redux,性能優(yōu)異且靈活強大县忌。API相當(dāng)簡單掂榔,包括一個Provider組件和一個connect高階方法继效。

  • Provider

Provider是store提供者。只要把組件樹根節(jié)點包裹在Provider中装获,整個組件樹上的節(jié)點都可以通過connect獲取store:

ReactDOM.render(
  <Provider store={store}>
    <MyRootComponent />
  </Provider>
);
  • connect

connect是用來“連接”store與組件的方法瑞信,用法如下:

import { add } from 'actions';

function mapStateToProps(state) {
    return {
        num: state.num
    };
}

function mapDispatchToProps(dispatch) {
    return {
        onBtnClick() {
            dispatch(add()); // add()為action creator
        }
    };
}

function Counter(props) {
    return (
      <p>
        {props.num}
        <button onClick={props.onBtnClick}>+1</button>
      </p>
    );
}

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

在這個示例中,我們通過connect讓組件Counter得以連接store穴豫,從store中取得num信息并在按鈕單擊時觸發(fā)store上的add方法喧伞。

  • enhancer

connect()的執(zhí)行結(jié)果是一個“高階組件”,我們稱之為enhancer绩郎。
高階組件指符合以下條件的函數(shù):接收一個已有的組件作為參數(shù)潘鲫,返回一個新組件,后者將前者封裝于內(nèi)部肋杖。一般使用高階組件都是為了對已有組件進(jìn)行某些能力上的增強溉仑。
這里enhancer對傳入組件進(jìn)行怎樣的增強呢?答案便是接觸store的能力状植。
原有組件Counter不直接與store打交道浊竟,甚至不知道store與Redux的存在,而經(jīng)過enhancer處理得到的組件津畸,即上例中最終被export的內(nèi)容振定,能夠直接接觸到store,監(jiān)聽肉拓、讀取狀態(tài)數(shù)據(jù)并觸發(fā)action后频。這里的store,就是先前通過Provider引入的暖途。

react-redux通過React在0.1.4版引入的context特性實現(xiàn)了store內(nèi)容的隱式傳遞:Provider作為整個組件樹的根節(jié)點卑惜,通過實現(xiàn)getChildContext方法將store提供給它的的子孫們,而enhancer通過組件的context屬性獲取store對象驻售,從而可以調(diào)用其提供的subscript露久、getState、dispatch等方法欺栗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毫痕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子迟几,更是在濱河造成了極大的恐慌消请,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘤旨,死亡現(xiàn)場離奇詭異梯啤,居然都是意外死亡,警方通過查閱死者的電腦和手機存哲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門因宇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來七婴,“玉大人,你說我怎么就攤上這事察滑〈蚶澹” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵贺辰,是天一觀的道長户盯。 經(jīng)常有香客問我,道長饲化,這世上最難降的妖魔是什么莽鸭? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮吃靠,結(jié)果婚禮上硫眨,老公的妹妹穿的比我還像新娘。我一直安慰自己巢块,他們只是感情好礁阁,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著族奢,像睡著了一般姥闭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上越走,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天棚品,我揣著相機與錄音,去河邊找鬼弥姻。 笑死南片,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庭敦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼薪缆,長吁一口氣:“原來是場噩夢啊……” “哼秧廉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拣帽,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤疼电,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后减拭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔽豺,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年拧粪,在試婚紗的時候發(fā)現(xiàn)自己被綠了修陡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沧侥。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖魄鸦,靈堂內(nèi)的尸體忽然破棺而出宴杀,到底是詐尸還是另有隱情,我是刑警寧澤拾因,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布旺罢,位于F島的核電站,受9級特大地震影響绢记,放射性物質(zhì)發(fā)生泄漏扁达。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一蠢熄、第九天 我趴在偏房一處隱蔽的房頂上張望罩驻。 院中可真熱鬧,春花似錦护赊、人聲如沸惠遏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽节吮。三九已至,卻和暖如春判耕,著一層夾襖步出監(jiān)牢的瞬間透绩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工壁熄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留帚豪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓草丧,卻偏偏與公主長得像狸臣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子昌执,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

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