国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網站 > WEB開發 > 正文

React×Redux——react-redux庫connect()方法與Provider組件

2024-04-27 15:07:01
字體:
來源:轉載
供稿:網友

在寫Redux的時候我們就了解了 如果使用Redux的話配合React是最好的 Dan Abramov為此還特意封裝了一個react-redux庫來提供便利

概念

一旦我們選擇使用了這個react-redux庫 那么我們的組件概念就要加以區分了 從現在起我們的組件分為展示組件和容器組件兩種 (參考了通俗易懂的阮大神博客)

展示組件

展示組件(PResentational component) 也叫UI組件、純組件 特點如下:

負責UI顯示無狀態不使用this.state數據來自this.props不使用任何redux的API

展示組件其實就是把我們的普通組件的數據與邏輯抽離出來

容器組件

容器組件(container component) 特點如下:

負責管理數據和業務邏輯帶有內部狀態使用redux的API

容器組件是由我們react-redux庫的API通過展示組件生成的

關系

從它們的名字也可以猜到,它們是內外關系 容器組件包裹著展示組件

優勢

說的再通俗一些 我們原來是將結構和邏輯都裝在一個組件中 現在將這個組件繼續拆成負責視圖的組件和負責邏輯數據的組件 這樣做有如下優點:

理解 數據與邏輯分開,更便于我們理解分離 必須將標簽拆分,可用性更強重用 一個展示組件可以搭配不同容器組件視圖 展示組件可以放到單獨頁面中調整UI

下面我們來看一下react-redux庫的核心 connect()方法與Provider組件

connect

上面也說到了 我么的容器組件是由庫API得到的 而這個函數就是connect connect的意思就是連接展示組件與容器組件的意思 為了加以區分,我用Container表示容器組件,用Component表示展示組件 用法如下

import {connect} from 'react-redux';const Container = connect()(Component);

結構就是這個樣子

<Container> <Component/></Container>

不過現在我們僅僅是通過展示組件生成了一個容器組件 并且將它們連接了起來 但是容器組件中并沒有數據和邏輯 只是一具空殼,毫無意義 所以我們還需要向這個connect函數中傳入兩個參數 它接收兩個值作為參數:(實際是四個,另外兩個不常用暫時不講)

mapStateToProps(輸入邏輯) 負責將通過state獲得的數據映射到展示組件的this.propsmapDispatchToProps(輸出邏輯) 負責將用戶操作轉化為Action的功能函數映射到展示組件的this.props

名字就和reducer一樣,只是官方的概念性叫法(不過還是蠻形象的) 使用的時候可以自定義名字(不過一定要語義化)

所以完整的用法應該是這樣的

const Container = connect( mapStateToProps, mapDispatchToProps)(Component);

但是此時mapStateToProps與mapDispatchToProps我們還沒有定義

mapStateToProps

mapStateToProps負責將state的數據映射到展示組件的this.props 它是一個函數,接收參數state對象 如果有必要的話,還可以使用第二個參數:容器組件的props屬性 返回一個對象表示state到展示組件props的映射關系

const mapStateToProps = (state) => { return { list: state.list }}

此時你會發現這個函數名有多合適

返回對象中的“值”—— state.list 表示我們要將state的list數組傳遞給內部的展示組件返回對象中的“鍵”—— list 表示我們在展示組件中可以通過this.props.list來獲取這個數組

但有時,我們不能這么輕松的就通過state的某個屬性值獲得要傳遞的數據 這時我們可以自定義一個處理函數返回要傳遞的數據

const mapStateToProps = (state) => { return { list: handler(state.list, state.option); }}

比如說這里handler就是我們的處理函數 拿我上一篇文章的toDoList待辦事項列表為例 這個handler大概是這樣的

const handler = (list, option) => { switch(option){ case "SHOW_ACTION": return list.filter(...); case "SHOW_CROSSED": return list.filter(...); ... default: return list; }}

這個函數我沒有寫完整,相信大家應該都能看明白 通過判斷option我來將list數組進行 “過濾” 函數返回后作為數據返回給展示組件


mapStateToProps會訂閱store,state更新后,就會觸發展示組件重繪 不過在connect( )函數中,我們可以省略mapStateToProps 如果這么做的話,store更新就不會觸發展示組件重繪了

上面也說道了,除了state我們還可以使用容器組件的屬性props

const mapStateToProps = (state, ownProps) => { return { ... }}

如果容器組件的props發生改變的話,同樣會觸發展示組件重繪

mapDispatchToProps

mapDispatchToProps負責定義發送action的函數映射到展示組件的this.props 與它的兄弟不同,它既可以是函數也可以是對象 作為函數,它會得到store.dispatch作為參數 同樣還有一個容器組件的props屬性可以使用 返回值我不用說大家也能猜到 就是一個表示映射關系的對象 但是這里表示的是用戶如何發出Action(比如觸發事件)

const mapDispatchToProps = (state, ownProps) => { return { onClick: () => { dispatch({ type: 'SET_FILTER', filter: ownProps.filter }) } }}返回對象中的“值”—— () => {dispatch(...)} 表示我們要傳遞給內部展示組件的函數(函數功能:dispatch一個action)返回對象中的“鍵”—— onClick 表示我們在展示組件中可以通過this.props.onClick來獲取這個函數

如果是作為對象的話,就更簡單了 上面的寫法和下面的等價

const mapDispatchToProps = { onClick: (filter) => { type: 'SET_FILTER', filter: filter }}

這個對象的值是一個函數,它被認為是一個Action Creator 函數的參數可以填入容器組件的props 返回的Action會由redux自動dispatch

Provider

在完成了Container與Componet的連接 實現了Container的管理數據與業務邏輯之后還沒完 還有問題 我們使用了mapStateToProps,它的參數是state 也就是說,他需要傳入state 如果我們手動將state對象一層一層的傳入容器組件 應用小還好說,大應用深層的組件簡直累死了,絕對讓你傳到懷疑人生

好在,react-redux提供了Provider組件讓我們省了不少功夫 它就相當于我們整體的容器組件(不過區別很大) 用法就是在我們根組件外部嵌套一層Provider,傳入store (使用全局的store有風險) 這樣所以的子組件都可以開心地拿到state了 我們也省心了

render( <Provider store={store}> <App/> </Provider>, document.getElementById('root'));

內部的原理是: Provider接受store作為其props,并聲明為context的屬性之一 子組件在聲明了contextTypes之后可以通過this.context.store訪問到store

小實例

上一次介紹Redux的時候介紹了一個簡單的計數器 這次我把那個代碼拿過來改裝一下

import React from 'react';import {Component} from 'react'import ReactDom from 'react-dom';import {createStore, combineReducers} from 'redux';import {connect, Provider} from 'react-redux';

首先定義單純用來展示UI的展示組件

class Counter extends Component { render(){ const {value, reduceHandler, addHandler} = this.props; return ( <div> <p>{value}</p> <button onClick={reduceHandler}>-</button> <button onClick={addHandler}>+</button> </div> ) }};

然后定義映射函數,生成容器組件

const mapStateToProps = (state) => { return { value: state.cnt }}const mapDispatchToProps = (dispatch) => { return { reduceHandler: () => { dispatch({type: 'REDUCE'}); }, addHandler: () => { dispatch({type: 'ADD'}); } }}const APP = connect(mapStateToProps, mapDispatchToProps)(Counter);

Reducer稍微修改一下

const reducer = (state = {cnt: 0}, action) => { switch (action.type) { case 'ADD': return {cnt: state.cnt + 1}; case 'REDUCE': return {cnt: state.cnt - 1}; default: return state; }};const store = createStore(reducer);

渲染函數中的結構外部嵌套Provider并添加store

ReactDom.render( <Provider store={store}> <APP/> </Provider>, document.getElementById('root'));

有了Provider,我們也就不需要 store.dispatch() 了 它會幫我們處理渲染 最后的樣式依然是那個樣子

==主頁傳送門==


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 恩施市| 绵阳市| 南靖县| 千阳县| 平陆县| 富源县| 白城市| 靖边县| 安福县| 湾仔区| 南通市| 徐汇区| 宝丰县| 蓬莱市| 密山市| 调兵山市| 安义县| 兴隆县| 行唐县| 游戏| 英德市| 于都县| 夏津县| 米脂县| 阿拉善盟| 呼和浩特市| 广灵县| 罗源县| 万州区| 灵山县| 奉节县| 长葛市| 永德县| 吉隆县| 重庆市| 虞城县| 广东省| 察雅县| 安新县| 余姚市| 牡丹江市|