「推薦」React 通信之 Redux,看這一篇就能掌握

背景

React 組件 componentDidMount 的時候初始化 Model,並監聽 Model 的 change 事件,當 Model 發生改變時調用 React 組件的 setState 方法重新 render 整個組件,最後在組件 componentWillUnmount 的時候取消監聽並銷燬 Model。

「推薦」React 通信之 Redux,看這一篇就能掌握

第一部分 Redux的出現

存在即合理

下圖左側所示,react單向流動的特性,導致在複雜的狀態管理面前,會越來越麻煩。Redux的出現就是為了解決state裡面的數據問題。

下圖右側所示,redux維護單一狀態庫。

Redux三大特性:

1 唯一數據源

2 保持只讀狀態

3 數據改變只能通過純函數來執行


「推薦」React 通信之 Redux,看這一篇就能掌握

第二部分 Redux概念

一、粗略認識

首先回想下,曾經你去圖書館借書的場景+上圖右側樹圖。

  • 去圖書館;
  • 詢問管理員是否有《西部世界iii》這本書;
  • 管理員查閱庫存;
  • 反饋給你,自己網上找資源去;
  • 你去網上找資源。

這個流程其實包含了Redux的整個流程。

詢問 + 查閱 = 反饋。即:action + state = new state

有果必有因

「推薦」React 通信之 Redux,看這一篇就能掌握

「推薦」React 通信之 Redux,看這一篇就能掌握

「推薦」React 通信之 Redux,看這一篇就能掌握

二、具體的概念

React-Redux 將所有組件分成兩大類:UI 組件(presentational component)和容器組件(container component)。

UI 組件負責 UI 的呈現,容器組件負責管理數據和邏輯

你可能會問,如果一個組件既有 UI 又有業務邏輯,那怎麼辦?回答是,將它拆分成下面的結構:外面是一個容器組件,裡面包了一個UI 組件。前者負責與外部的通信,將數據傳給後者,由後者渲染出視圖。

React-Redux 規定,所有的 UI 組件都由用戶提供,容器組件則是由 React-Redux 自動生成。也就是說,用戶負責視覺層,狀態管理則是全部交給它。

以上摘錄自---阮一峰的網絡日誌,建議初學者多讀幾遍。

  • Action: 把數據從應用傳到 store 的有效載荷;
  • Store: 保存數據的地方;
  • Dispatcher: view發出Action的唯一辦法;
  • Reducer: Store收到Action以後,必須給出一個新的state,這樣view才會發生變化。Reducer即根據Action計算state;
  • State: store裡面存儲的數據。
「推薦」React 通信之 Redux,看這一篇就能掌握

「推薦」React 通信之 Redux,看這一篇就能掌握

三、示例代碼

Redux一個簡單的加數操作,涉及完整的流程。

其中涉及

  • redux各個概念;
  • UI組件 & 容器組件 的相互關係;
  • Provider的使用
<code>import React, { Component } from "react";
import PropTypes from "prop-types";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";

// 生成組件
class Counter extends Component {
render() {
const { value, onIncreaseClick } = this.props;
return (

{value}
<button>Increase/<button>

);
}
}

Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncreaseClick: PropTypes.func.isRequired
};

// 定義action
const increaseAction = { type: "increase" };

/**
* Reducer函數
* @param {*} state 默認值
* @param {*} action 根據action來計算state.
*/
function counter(state = { count: 0 }, action) {
const count = state.count;
switch (action.type) {
case "increase":
return { count: count + 1 };
default:
return state;
}
}

/**
* 創建store -> 需要reducer -> 默認值+action
*/

const store = createStore(counter);

/**
* 建立一個從(外部的)state對象到(UI 組件的)props對象的映射關係。
* @param {*} state
*/
function mapStateToProps(state) {
return {
value: state.count
};
}

/**
* 建立 UI 組件的參數到store.dispatch方法的映射
* 定義了哪些用戶的操作應該當作 Action,傳給 Store。
* 它可以是一個函數,也可以是一個對象。
*
* 1. 函數:
* - 參數:
* 可以拿到dispatch和ownProps(容器組件的props對象)兩個參數;
* - 返回值
* 一個對象,每個鍵值對都是一個映射,[鍵名對應函數名]
* 定義了 UI 組件的參數怎樣發出 Action。
* 2. 對象
* 它的每個鍵名也是對應 UI 組件的同名參數,鍵值應該是一個函數,
* 會被當作 Action creator ,返回的 Action 會由 Redux 自動發出。
* @param {*} dispatch
*/
function mapDispatchToProps(dispatch) {
return {
// 同名函數 onIncreaseClick, dispatch 一個action

onIncreaseClick: () => dispatch(increaseAction)
};
}

/**
* connect 自動生成容器組件,將UI組件[Counter]與[容器組件]即關聯起來。
* Counter: UI 組件
* mapStateToProps: 輸入邏輯:外部的數據(即state對象)如何轉換為 UI 組件的參數
* mapDispatchToProps: 用戶發出的動作如何變為 Action 對象,從 UI 組件傳出去。
*/
const App = connect(
mapStateToProps,
mapDispatchToProps
)(Counter);

// React-Redux 提供Provider組件,可以讓容器組件拿到state。
// Provider在根組件外面包了一層,這樣一來,App的所有子組件就默認都可以拿到state了
// 原理: React中的context屬性,
ReactDOM.render(
<provider>

/<provider>,
document.getElementById("root")
);
/<code>

結合下圖理解

「推薦」React 通信之 Redux,看這一篇就能掌握

圖片來源:https://juejin.im/post/5acdbe8f51882548fe4a7af1

總結

這個例子中,最外層的Provider利用react-redux中的provider組件,那麼究竟provider組件做了什麼?為何provider子組件能夠或許context屬性?

上篇文章利用context進行傳值,並未過多的解釋說明。

Provider 本身是一個 react 組件,這一點首先要搞清楚。它的實現原理非常簡單,利用了 React 的 context 這一特性。文檔Context - React, 只要在最外層的組件實現一個 getChildContext 這個方法,返回一個對象,內部的組件都可以通過 this.context 拿到這個對象。所以一個簡單的 Provider 實現是這樣的:

<code>class Provider extends React.Component {
getChildContext() {
return { store: this.props.store }
}

render() {
return this.props.children
}
}

// usage
const store = createStore();
ReactDOM.render(
<provider>

/<provider>
, document.querySelector('#root'));/<code>

那麼整個頁面的邏輯流程就是:

  1. 創建Store,createStore(), 接受reducers&默認值;
  2. createStore 對每一個reducer進行dispatch一個action.type=@@redux/INTT類型的action,然後返回state默認值;
  3. render()進行渲染,每個子組件通過傳入的this.context.store.getState()方法獲取state對象+ownProps給mapStateToProps方法,構建props,應用到子組件上;
  4. UI組件觸發action, 隨即mapDispatchToProps觸發相應的action;
  5. strore接收到action進行reduce,得到新的state,然後再調用所有子組件的mapDispatchToProps生成props.
  6. 最後provider進行重新渲染需要更新的組件。

第三部分

react-redux示例--TodoList demo

試著從頭到位實現一邊,會更加深對本文的理解。鑑於代碼太多&上述的理解,應該是沒問題的,但不要眼高手低。

「推薦」React 通信之 Redux,看這一篇就能掌握

感謝

<code>一幅圖明白React-Redux的原理
解析:讓你弄懂redux原理
https://www.cnblogs.com/nayek/p/12369418.html
https://www.processon.com/view/5db55958e4b0e433944fdc87
https://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html/<code>


分享到:


相關文章: