Redux-Part-I

Redux

React Redux

Flux 的實作之一

有一個共同的 Store 儲存資料

透過 Middleware 來控制工作流

發起 Action 來通過工作流之後

透過 Reducer 來修改 Store 內的資料

再藉由 Store 的資料來顯示 Screen

搭配的 Package 有很多種不同的配合與實現

  • redux-thunk
  • redux-saga

主要都是在處理 Async Actions

redux-thunk skelton

redux-saga skelton

兩個骨架範例

基本上每一個 Async Action 都是單一的 Promise

但是不代表只能夠有一個 Promise

也可以多個 Promise 但是需要使用 Promise.all 做群組

有清楚的成功與失敗

所以建立一個非同步的 Action 應該會有三個 action types

  • Request - 顯示 loading
  • Success - 成功 (關閉 loading)
  • Error - 失敗 (關閉 loading)

不要跳脫一個完整的週期

image

在一個 Action 內 在發送另外一個 非同步 Action

Install And Setup

Basic Usage

1
$ yarn add redux
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import {createStore} from 'redux';
import React, {useState, useEffect} from 'react';
import {Navigation} from 'react-native-navigation';
import { View, Text, Button, StyleSheet, Icon } from 'react-native';

const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};


const store = createStore(counter);

const LoginScreen = () => {
const [value, setValue] = useState(null);
useEffect(() => {
setTimeout(() => {
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1
}, 2000)
const unsubscribe = store.subscribe(() => {
const v = store.getState();
console.log('LoginScreen -> v', v)
setValue(v);
})
return () => unsubscribe();
}, [])
return (
<View style={styles.root}>
<Text>{String(value)}</Text>
<Button
title='Login'
color='#710ce3'
onPress={() => Navigation.setRoot(mainRoot)}
/>
</View>
);
};

counter 是 Reducer

Reducer 都是一個函式

會修改 Store 裡面的某一個部分的值

再把修改結果回傳

但是這樣最基本的 Redux 只能同步的修改 Store 的資料

{ type: 'INCREMENT' } 是 Action Object

Middleware

但是上述的流程只能處理同步的 Action

非同步的需要多做一點點事情

這時候需要 Middleware 的幫助

Middleware 概念就是一個一個的生產線

每一個 Function 都是處理某些細節

再利用這個 Middleware 排定順序

Compose

redux compose

1
2
3
4
5
const compose = (...fns) => (...payload) => {
if(fns.length === 0) return payload;
if(fns.length === 1) return fns[0](...payload);
return funcs.reduce((a, b) => (...payload) => a(b(...payload)))
}

composepipe 是 Middleware 的其中兩種應用

針對 Dispatch 做擴充

目前 dispatch 只能做同步 Action

但是並不符合我們的需求

Monkeypatching

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default (...middlewares) => (reducer, initialState) => {
const store = createStore(reducer, initialState);
const next = store.dispatch;

const middlePayload = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
};

const chain = middlewares.map(middleware => middleware(middlewareAPI));
const dispatch = compose(...chain)(store.dispatch);
return {
...store,
dispatch
}
};

可以一步一步慢慢了解 Redux 如何形成 Middleware 的過程

最後可以看到這個範例

The Final Approach

接下來了解如何實做 Redux 中的 Middleware 之後

再來看看加入 Thunk , Saga 概念的 Data flow

參考資源

Nodejs 範例

Middleware

文章目录
  1. 1. Redux
    1. 1.1. React Redux
  2. 2. Install And Setup
    1. 2.1. Basic Usage
    2. 2.2. Middleware
      1. 2.2.1. Compose
    3. 2.3. 針對 Dispatch 做擴充
  3. 3. 參考資源
    1. 3.1. Nodejs 範例
|