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