日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

react-redux集中式狀態管理及基本使用與優化_React

作者:codeMak1r.小新 ? 更新時間: 2022-10-19 編程語言

1、react-redux

react-redux把組件分為兩類,一類叫做UI組件,一類叫做容器組件;

UI組件的外側都要包裹一個容器組件。

注意??:本文使用的示例為之前的文章中的示例。在之前的文章中已經做過了介紹,在本文就不再闡述。

建議閱讀順序是:
【redux工作流程】
【redux異步action】
??再到本文

2、連接容器組件與UI組件

UI組件存放在components文件夾中,我們可以在src目錄下新建文件夾containers,專門用于存放容器組件

例如:Count組件的容器組件:/src/containers/Count/index.jsx

/*
  該組件是Count組件這個UI組件的容器組件
 */
// 引入Count組件的UI組件
import CountUI from '../../components/Count'
// 引入connect用于連接UI組件與容器組件
import { connect } from 'react-redux'

//創建并暴露一個Count的容器組件,connect()()的含義是:調用connect()這個函數返回的函數
export default connect()(CountUI)

代碼解釋:

引入CountUI,為Count組件的UI組件,從原理圖中來看,該組件是Count容器組件的子組件。

引入connect函數,用于連接UI組件與容器組件;

我們從原理圖中可以看出,redux要想工作,必須要連接UI組件與容器組件,還必須連接容器組件與store。

那么我們在容器組件中,使用connect()()的方法連接了UI組件

【connect()()的含義:調用connect()這個函數的返回值,返回值本身是一個函數,也就是調用返回的函數】

現在還需要讓容器組件與store建立起連接;

怎么讓容器組件與store建立起連接呢?

我們之前在App組件中一直都是渲染Count的UI組件的,但是我們現在引入了Count的容器組件(為Count的UI組件的父組件),那么我們可以直接在App組件中直接渲染Count組件的容器組件:

// App.jsx
import React, { Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>
      	{/* 給容器組件傳遞store */}
        <Count store={store} />
      </div>
    )
  }
}

重點??在于,

在渲染Count組件的容器組件時,通過組件的props屬性,將store傳入Count組件的容器組件,從而實現容器組件與store建立起連接。

3、react-redux基本使用

現在我們已經把UI組件與容器組件建立起連接了,并且將容器組件與store也建立起連接了,那么我們接下來一起來探索react-redux是怎么工作,如何使用的呢?

從流程圖可以看出,我們需要向UI組件傳遞state(狀態)和dispatch(操作狀態的方法)。

但是我們在UI組件的父組件,也就是Count的容器組件中,并沒有以組件標簽()的形式去渲染子組件

而是通過react-redux提供的connect方法將父子組件建立起的聯系,我們就需要通過connect方法傳遞props。

我們之前知道,我們在調用connect方法返回的函數時需要傳遞UI組件作為參數,以將容器組件與UI組件連接起來,也就是

connect()(CountUI)

而傳遞props時,我們需要在調用connect方法時直接傳入兩個參數(也就是connect的第一個括號內的參數),并且這兩個參數都是函數形式的參數。具體看代碼吧~

connect(mapStateToProps, mapDispatchToProps)(CountUI)

說明:第一個函數參數mapStateToProps作用是將存放在store中的狀態映射給UI組件的props;

第二個函數參數mapDispatchToProps作用是將操作數據的方法映射給UI組件的props;

其實也就對應圖中的

具體實現如下:

/*
  該組件是Count組件這個UI組件的容器組件
 */
import CountUI from '../../components/Count'
import { connect } from 'react-redux'
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action_creator'
/* 
  1.mapStateToProps函數返回的是一個對象;
  2.返回的對象中的key就作為傳遞給UI組件props的key,value就作為傳遞給UI組件props的value
  3.mapStateToProps用于傳遞狀態
*/
function mapStateToProps(state) {
  return { count: state }
}

function mapDispatchToProps(dispatch) {
  return {
    jia: (data) => {
      // 通知redux執行加法
      dispatch(createIncrementAction(data))
    },
    jian: (data) => {
      dispatch(createDecrementAction(data))
    },
    jiaAsync: (data, time) => {
      dispatch(createIncrementAsyncAction(data, time))
    }
  }
}

//創建并暴露一個Count的容器組件,connect()()的含義是:調用connect()這個函數返回的函數
export default connect(mapStateToProps, mapDispatchToProps)(CountUI)

這樣一來,Count的UI組件就會接收到傳遞進來的props,我們可以通過props去渲染狀態和操作狀態:

/src/components/Count/index.jsx:

渲染狀態:

<h1>當前求和為:{this.props.count}</h1>

操作狀態:

// 加法
increment = () => {
  const { value } = this.selectedNumber
  this.props.jia(value * 1)
}
// 減法
decrement = () => {
  const { value } = this.selectedNumber
  this.props.jian(value * 1)
}
// 和為奇數時,加
incrementIfOdd = () => {
  const { value } = this.selectedNumber
  if (this.props.count % 2 !== 0) {
    this.props.jia(value * 1)
  }
}
// 異步加
incrementAsync = () => {
  const { value } = this.selectedNumber
  this.props.jiaAsync(value * 1, 500)
}

react-redux基本使用總結:

明確兩個概念:UI組件與容器組件

UI組件:不能使用任何redux的api,只負責頁面的呈現、交互等等;

容器組件:負責和redux通信,將結果交給UI組件

如何創建一個容器組件——靠react-redux 的 connect函數

connect(mapStateToProps, mapDispatchToProps)(CountUI)

mapStateToProps——映射狀態,返回值是一個對象;

mapDispatchToProps——映射操作狀態的方法,返回值是一個對象

備注:容器組件中的store是靠props傳入的,而不是在容器組件中直接引入。

優化1、簡寫mapState和mapDispatch兩個映射方法

原映射方法:

function mapStateToProps(state) {
  return { count: state }
}

function mapDispatchToProps(dispatch) {
  return {
    jia: (data) => {
      // 通知redux執行加法
      dispatch(createIncrementAction(data))
    },
    jian: (data) => {
      dispatch(createDecrementAction(data))
    },
    jiaAsync: (data, time) => {
      dispatch(createIncrementAsyncAction(data, time))
    }
  }
}

簡寫成箭頭函數:

const mapStateToProps = state => ({ count: state })

const mapDispatchToProps = dispatch => (
  {
    jia: (data) => {
      // 通知redux執行加法
      dispatch(createIncrementAction(data))
    },
    jian: (data) => {
      dispatch(createDecrementAction(data))
    },
    jiaAsync: (data, time) => {
      dispatch(createIncrementAsyncAction(data, time))
    }
  }
)

當然,這只是在編碼的角度對函數進行簡化,我們還可以在API的角度,實現mapDispatch更為簡潔的寫法。

其實mapDispatchToProps還可以是一個對象,在一般寫法中,mapDispatchToProps是一個函數,但是可以簡寫成一個對象。

export default connect(
  state => ({ count: state }),

  // mapDispatchToProps的簡寫——是一個對象
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }

  // mapDispatchToProps一般寫法——是一個函數
  /* dispatch => (
    {
      jia: (data) => {
        // 通知redux執行加法
        dispatch(createIncrementAction(data))
      },
      jian: (data) => {
        dispatch(createDecrementAction(data))
      },
      jiaAsync: (data, time) => {
        dispatch(createIncrementAsyncAction(data, time))
      }
    }
  ) */
)(CountUI)

把mapDispatchToProps簡寫成一個對象的話,react-redux會自動分發,也就是底層自動調用dispatch方法,所以我們在書寫代碼時并不需要手動調用dispatch方法,在mapDispatchToProps簡寫成一個對象時可以省略dispatch,這就是屬于API層面的優化。

優化2、Provider組件的使用

在前面的連接容器組件和store的講解中,我們提出:要想連接容器組件和store,就需要在App.jsx中通過props將store傳入容器組件中。也就是這樣子的:

// App.jsx
import React, { Component } from 'react'
import Count from './containers/Count'
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>
      	{/* 給容器組件傳遞store */}
        <Count store={store} />
      </div>
    )
  }
}

現在我們基于react-redux,可以對App組件進行優化:

// App.jsx
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import Count from './containers/Count'
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>
        {/* 給容器組件傳遞store */}
        <Provider store={store}>
          <Count />
        </Provider>
      </div>
    )
  }
}

這樣一來,哪怕我們需要連接多個容器組件到store,都只需要在渲染組件標簽的外圍包裹一個< Provider>標簽即可。

優化3、整合UI組件與容器組件

前面兩個優化,我們分別從代碼層面和API層面進行了優化。在這里,我們將在文件層面對UI組件和容器組件進行優化。

我們前面在逐步學習實踐react-redux時,將容器組件放在containers文件夾中。但是我們發現,如果需要使用redux的UI組件越來越多的話,需要的容器組件也越來越多,到最后可能項目中有20個組件需要使用redux中的狀態,那么我們真的就另外創建20個容器組件嗎?

Of course not ! Of course not! Ofcoursenot!

其實我們可以將UI組件與容器組件整合在同一個文件內!

/src/containers/Count/index.jsx:

import React, { Component } from 'react'
// 引入connect用于連接UI組件與容器組件
import { connect } from 'react-redux'
import {
  createIncrementAction,
  createDecrementAction,
  createIncrementAsyncAction
} from '../../redux/count_action_creator'

// 定義UI組件Count
class Count extends Component {
  // 加法
  increment = () => {
    const { value } = this.selectedNumber
    this.props.jia(value * 1)
  }
  // 減法
  decrement = () => {
    const { value } = this.selectedNumber
    this.props.jian(value * 1)
  }
  // 和為奇數時,加
  incrementIfOdd = () => {
    const { value } = this.selectedNumber
    if (this.props.count % 2 !== 0) {
      this.props.jia(value * 1)
    }
  }
  // 異步加
  incrementAsync = () => {
    const { value } = this.selectedNumber
    this.props.jiaAsync(value * 1, 500)
  }

  render() {
    return (
      <div>
        <h1>當前求和為:{this.props.count}</h1>
        <select ref={currentNode => { this.selectedNumber = currentNode }}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>&nbsp;&nbsp;&nbsp;
        <button onClick={this.increment}>加</button>&nbsp;
        <button onClick={this.decrement}>減</button>&nbsp;
        <button onClick={this.incrementIfOdd}>和為奇數時,加</button>&nbsp;
        <button onClick={this.incrementAsync}>異步加</button>
      </div>
    )
  }
}
// 創建并暴露一個Count的容器組件,connect()()的含義是:調用connect()這個函數返回的函數
export default connect(
  state => ({ count: state }),
  // mapDispatchToProps的簡寫——是一個對象
  {
    jia: createIncrementAction,
    jian: createDecrementAction,
    jiaAsync: createIncrementAsyncAction
  }
  // mapDispatchToProps一般寫法——是一個函數
)(Count)

如此一來,我們就可以刪除/src/components/Count/index.jsx了~

優化總結

容器組件和UI組件整合為同一個文件

無需自己給容器組件傳遞store,給包裹一個標簽,在Provider內傳遞store即可;

使用了react-redux后也不用再自己監測redux中狀態的改變了,容器組件可以自動完成這個工作;

mapDispatchToProps也可以簡單的寫成一個對象;

一個組件要和redux“打交道”要經過哪幾步?

定義好UI組件——不暴露;引入connect生成一個容器組件,并暴露,寫法如下:
 connect(
	state => ({key:value}), //映射狀態
	{key:xxxxAction}  //映射操作狀態的方法
 )(UI組件)
  1. 在UI組件中通過this.props讀取和操作狀態。

原文鏈接:https://blog.csdn.net/Svik_zy/article/details/125951641

欄目分類
最近更新