摘要:和的結(jié)合簡(jiǎn)述相信很多前端開(kāi)發(fā)者都聽(tīng)說(shuō)或使用過(guò),我曾寫過(guò)一篇關(guān)于快速理解的文章,雖說(shuō)是快速理解,但實(shí)際上更應(yīng)該叫做復(fù)習(xí)吧。它通過(guò)高階函數(shù),純函數(shù)使我們?cè)诰帉懡M件時(shí)完全不用接觸相關(guān)內(nèi)容,只通過(guò)將組件和數(shù)據(jù)連接起來(lái)即可。
react-redux react和redux的結(jié)合 簡(jiǎn)述
相信很多前端開(kāi)發(fā)者都聽(tīng)說(shuō)或使用過(guò)react-redux,我曾寫過(guò)一篇關(guān)于快速理解redux的文章,雖說(shuō)是快速理解,但實(shí)際上更應(yīng)該叫做復(fù)習(xí)redux吧。本文也只是講述react-redux的思想及原理,對(duì)于細(xì)節(jié)實(shí)現(xiàn)則不贅述。
一、初始化工程我們先create-react-app新建一個(gè)react項(xiàng)目,然后安裝第三方庫(kù)cnpm install --save prop-types
我們?cè)趕rc目錄下新建3個(gè)文件,Header.js、Content.js、ThemeSwitch.js
組件結(jié)構(gòu)是這樣的
運(yùn)行起來(lái)是這樣的
我們先構(gòu)建store,并且把它放在Index組件的context里面,那樣Index以下的所有組件都可以使用store了。
class Index extends Component { static childContextTypes = { store: PropTypes.object } getChildContext () { return { store } } render () { return () } }
我們修改Header,Content,ThemeSwitch,定義一個(gè)函_updateThemeColor在componentWillMount中調(diào)用
在該函數(shù)中獲取Index組件context里的store,并且將store里的colorState這只為自己文本的顏色
我們?cè)傩薷腡hemeSwitch,使按鈕綁定事件,點(diǎn)擊后執(zhí)行dispatch修改store里的state
此時(shí)我們點(diǎn)擊按鈕后,store里的數(shù)據(jù)確實(shí)改變了,可是頁(yè)面卻沒(méi)有改變,為何?
因?yàn)槲覀兒雎粤藄ubscribe,使得dispatch后_updateThemeColor函數(shù)并未執(zhí)行
我們分別給 Header.js、Content.js、ThemeSwitch.js 的 componentWillMount 生命周期都加上監(jiān)聽(tīng)數(shù)據(jù)變化重新渲染的代碼
代碼如下,僅以ThemeSwitch為例,其他文件類似
class ThemeSwitch extends Component { static contextTypes = { store: PropTypes.object } constructor () { super() this.state = { themeColor: "" } } componentWillMount () { const { store } = this.context this._updateThemeColor() store.subscribe(() => this._updateThemeColor()) } _updateThemeColor () { const { store } = this.context const state = store.getState() this.setState({ themeColor: state.themeColor }) } // dispatch action 去改變顏色 handleSwitchColor (color) { const { store } = this.context store.dispatch({ type: "CHANGE_COLOR", themeColor: color }) } render () { return () } }
到這里,我們已經(jīng)把react-redux的骨架搭建起來(lái)了
三、connect 和 mapStateToProps我們觀察剛剛寫的組件,他們存在兩個(gè)問(wèn)題
有大量重復(fù)邏輯
使用Connect高階組件解決
對(duì)context依賴過(guò)強(qiáng),可復(fù)用性過(guò)低
使用mapStateToProps解決
使用高階組件我們需要高階組件幫助我們從 context 取數(shù)據(jù),我們也需要寫 Dumb(純) 組件幫助我們提高組件的復(fù)用性。所以我們盡量多地寫 Dumb 組件,然后用高階組件把它們包裝一層,高階組件和 context 打交道,把里面數(shù)據(jù)取出來(lái)通過(guò) props 傳給 Dumb 組件。
這個(gè)高階組件被其銘文Connect,因?yàn)樗梢园?Dunb組件 和 context數(shù)據(jù) connect 起來(lái)
import React, { Component } from "react" import PropTypes from "prop-types" export const connect = (mapStateToProps) => (WrappedComponent) => { class Connect extends Component { static contextTypes = { store: PropTypes.object } render () { const { store } = this.context let stateProps = mapStateToProps(store.getState()) // {...stateProps} 意思是把這個(gè)對(duì)象里面的屬性全部通過(guò) `props` 方式傳遞進(jìn)去 return} } return Connect }
我們將新建一個(gè)react-redux文件,將Connect放進(jìn)去
我們?cè)诙x mapStateToProps函數(shù) 使它接收某參數(shù),返回相應(yīng)的數(shù)據(jù)。因?yàn)?strong>不同的組件需要store中不同的數(shù)據(jù)
import React, { Component } from "react" import PropTypes from "prop-types" import { connect } from "./react-redux" class Header extends Component { static propTypes = { themeColor: PropTypes.string } render () { return (React.js 小書(shū)
) } } const mapStateToProps = (state) => { return { themeColor: state.themeColor } } Header = connect(mapStateToProps)(Header) export default Header
此時(shí),Header 刪掉了大部分關(guān)于 context 的代碼,它除了 props 什么也不依賴,它是一個(gè) Pure Component,然后通過(guò) connect 取得數(shù)據(jù)。我們不需要知道 connect 是怎么和 context 打交道的,只要傳一個(gè) mapStateToProps 告訴它應(yīng)該怎么取數(shù)據(jù)就可以了。
此時(shí),Connect還未能監(jiān)聽(tīng)渲染,我們需要在Connect中創(chuàng)建渲染函數(shù)并且在componentWillMount中添加渲染函數(shù)
export const connect = (mapStateToProps) => (WrappedComponent) => { class Connect extends Component { static contextTypes = { store: PropTypes.object } constructor () { super() this.state = { allProps: {} } } componentWillMount () { const { store } = this.context this._updateProps() store.subscribe(() => this._updateProps()) } _updateProps () { const { store } = this.context let stateProps = mapStateToProps(store.getState(), this.props) // 額外傳入 props,讓獲取數(shù)據(jù)更加靈活方便 this.setState({ allProps: { // 整合普通的 props 和從 state 生成的 props ...stateProps, ...this.props } }) } render () { return} } return Connect }
現(xiàn)在已經(jīng)很不錯(cuò)了,Header.js 和 Content.js 的代碼都大大減少了,并且這兩個(gè)組件 connect 之前都是 Dumb 組件。接下來(lái)會(huì)繼續(xù)重構(gòu) ThemeSwitch。
mapDispatchToProps到目前為止,我們每次在更改數(shù)據(jù)時(shí),都要用過(guò)store.dispatch修改。
為了使組件更 Dunb(純) 我們對(duì)Connect和ThemeSwitch增加一個(gè)mapDispatchToProps 函數(shù),使ThemeSwitch組件擺脫對(duì)store.dispatch的依賴
export const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => { class Connect extends Component { static contextTypes = { store: PropTypes.object } constructor () { super() this.state = { allProps: {} } } componentWillMount () { const { store } = this.context this._updateProps() store.subscribe(() => this._updateProps()) } _updateProps () { const { store } = this.context let stateProps = mapStateToProps ? mapStateToProps(store.getState(), this.props) : {} // 防止 mapStateToProps 沒(méi)有傳入 let dispatchProps = mapDispatchToProps ? mapDispatchToProps(store.dispatch, this.props) : {} // 防止 mapDispatchToProps 沒(méi)有傳入 this.setState({ allProps: { ...stateProps, ...dispatchProps, ...this.props } }) } render () { return} } return Connect }
import React, { Component } from "react" import PropTypes from "prop-types" import { connect } from "./react-redux" class ThemeSwitch extends Component { static propTypes = { themeColor: PropTypes.string, onSwitchColor: PropTypes.func } handleSwitchColor (color) { if (this.props.onSwitchColor) { this.props.onSwitchColor(color) } } render () { return () } } const mapStateToProps = (state) => { return { themeColor: state.themeColor } } const mapDispatchToProps = (dispatch) => { return { onSwitchColor: (color) => { dispatch({ type: "CHANGE_COLOR", themeColor: color }) } } } ThemeSwitch = connect(mapStateToProps, mapDispatchToProps)(ThemeSwitch) export default ThemeSwitch
光看 ThemeSwitch 內(nèi)部,是非常清爽干凈的,只依賴外界傳進(jìn)來(lái)的 themeColor 和 onSwitchColor。但是 ThemeSwitch 內(nèi)部并不知道這兩個(gè)參數(shù)其實(shí)都是我們?nèi)?store 里面取的,它是 Dumb 的。
五、Provider我們要把所有和context有關(guān)的東西都分離出去,現(xiàn)在只有Index組件是被污染的
所以,我們?cè)趓eact-redux中新增Provider類,讓它包裹成為Index的高階函數(shù),包裹index
使組件結(jié)構(gòu)圖如下
代碼如下
export class Provider extends Component { static propTypes = { store: PropTypes.object, children: PropTypes.any } static childContextTypes = { store: PropTypes.object } getChildContext () { return { store: this.props.store } } render () { return ({this.props.children}) } }
... // 頭部引入 Provider import { Provider } from "./react-redux" ... // 刪除 Index 里面所有關(guān)于 context 的代碼 class Index extends Component { render () { return () } } // 把 Provider 作為組件樹(shù)的根節(jié)點(diǎn) ReactDOM.render(, document.getElementById("root") )
此時(shí),我們就把所有關(guān)于 context 的代碼從組件里面刪除了。
六、react-redux總結(jié)redux的思想就是有條理地,有規(guī)則地修改共享數(shù)據(jù)。而react里剛好有 context 這個(gè)東西可以被某組件以下的所有組件共享,為了在react中優(yōu)雅的修改context,react-redux就誕生了。它通過(guò)高階函數(shù)(Connect),純函數(shù)(mapStateToProps, mapDispatchToProps) 使我們?cè)诰帉懡M件時(shí)完全不用接觸context相關(guān)內(nèi)容,只通過(guò)Connect 將 Dumb組件 和 Context數(shù)據(jù) 連接起來(lái)即可。
參考react小書(shū)
完整代碼make-react-redux
本文如果有錯(cuò),歡迎指出
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/100241.html
摘要:簡(jiǎn)介是一個(gè)狀態(tài)管理的庫(kù),由基礎(chǔ)上開(kāi)發(fā)出來(lái),與的主要區(qū)別是只有一個(gè),關(guān)于,后文會(huì)詳述。這個(gè)函數(shù)接受四個(gè)參數(shù),它們分別是,,和。之前在注冊(cè)頁(yè)面,如果沒(méi)有滿足相關(guān)條件,則觸發(fā)的行為。具體定義了項(xiàng)目中觸發(fā)的行為類別,通過(guò)屬性來(lái)區(qū)別于不同的行為。 redux簡(jiǎn)介 redux是一個(gè)js狀態(tài)管理的庫(kù),由flux基礎(chǔ)上開(kāi)發(fā)出來(lái),與flux的主要區(qū)別是只有一個(gè)store,關(guān)于store,后文會(huì)詳述。在各...
摘要:介紹快速開(kāi)始是的官方綁定庫(kù)。通常你可以以下面這種方式調(diào)用方法基礎(chǔ)教程為了進(jìn)一步了解如何實(shí)際使用,我們將一步一步創(chuàng)建一個(gè)一個(gè)實(shí)例跳轉(zhuǎn)到 介紹 快速開(kāi)始 React-Redux是Redux的官方React綁定庫(kù)。它能夠使你的React組件從Redux store中讀取數(shù)據(jù),并且向store分發(fā)actions以更新數(shù)據(jù) 安裝 在你的React app中使用React-Redux: npm i...
摘要:它的作用就是像它的名字那樣,建立一個(gè)從外部的對(duì)象到組件的對(duì)象的映射關(guān)系。比如表示從整個(gè)的表示當(dāng)前組件容器的用來(lái)建立組件的參數(shù)到方法的映射比如表示它定義了哪些用戶的操作應(yīng)該當(dāng)作,傳給。 最近做的項(xiàng)目加入了react-redux,對(duì)react-redux一直沒(méi)理解透徹,最近有時(shí)間把react-redux梳理了一番,希望能夠幫助到大家, 首先有這幾個(gè)文件,action,reducer,sag...
摘要:我們可以為元素添加屬性然后在回調(diào)函數(shù)中接受該元素在樹(shù)中的句柄,該值會(huì)作為回調(diào)函數(shù)的第一個(gè)參數(shù)返回。使用最常見(jiàn)的用法就是傳入一個(gè)對(duì)象。單向數(shù)據(jù)流,比較有序,有便于管理,它隨著視圖庫(kù)的開(kāi)發(fā)而被概念化。 面試中問(wèn)框架,經(jīng)常會(huì)問(wèn)到一些原理性的東西,明明一直在用,也知道怎么用, 但面試時(shí)卻答不上來(lái),也是挺尷尬的,就干脆把react相關(guān)的問(wèn)題查了下資料,再按自己的理解整理了下這些答案。 reac...
摘要:應(yīng)用中唯一的狀態(tài)應(yīng)用的子組件例子方法來(lái)看下函數(shù)到底是如何將和組件聯(lián)系在一起的,注意到文檔中有這樣的一句話并不會(huì)改變它連接的組件,而是提供一個(gè)經(jīng)過(guò)包裹的組件。 關(guān)于React-redux Redux是React全家桶的重要一員,之前在知乎上也看到類似的提問(wèn):該如何通俗易懂的理解Redux? Redux是JavaScript的狀態(tài)容器,Redux的概念簡(jiǎn)單明了: 1. 應(yīng)用中所有的狀...
閱讀 3561·2021-09-22 10:52
閱讀 1588·2021-09-09 09:34
閱讀 1990·2021-09-09 09:33
閱讀 758·2019-08-30 15:54
閱讀 2598·2019-08-29 11:15
閱讀 713·2019-08-26 13:37
閱讀 1667·2019-08-26 12:11
閱讀 2975·2019-08-26 12:00