# [第06堂] Redux
## 什麼是Redux?
Redux 是一套除了 React 外在其他框架下也可以使用的**資料流管理工具**,他定義了資料流的規範,彌補了 React 在元件變多後狀態難以控管的問題,並將**資料集中管理**,讓程式更容易去維護和測試。
* #### action:包含更新資料的方式 action type 及更新資料時所用的值 action payload。
```javascript=
export const GET_ProjectInfo = (payload, callback) => {
return (dispatch) => {
dispatch({
type: "GET_ProjectInfo",
payload: payload,
callback: callback,
});
};
}
```
* #### dispatcher: 一個溝通用的函式,會接收 action 物件,執行 action 要做的事情,並傳遞資料給reducer。
* #### middlewares:對應接收到的 action 執行動作
```javascript=
const fetch = store => next => action => {
switch (action.type) {
case "GET_MeetingInfo":
_axios
.get(`/meeting?id=${action.payload}`,)
.then(response => {
if (response.status === 200) {
return response.data.data;
}
})
.catch(err => {
if (err.response.status === 401) {
localStorage.clear();
window.location.replace('http://localhost:3000/index');
}
alert(err.response.data.message);
throw new Error(err);
})
.then(json => {
if (action.callback) {
action.callback(json)
}
return next({
type: 'SAVE_MeetingInfo',
payload: json,
});
});
break;
...
```
* #### reducer:接收 dispatch 派發的 action,經過對應 action type 更新 state物件。
```javascript=
const initialState = {};
export default (state = initialState, action) => {
switch (action.type) {
case "SAVE_ProjectInfo":
return { ...state, ProjectInfo: action.payload };
case "SAVE_ProjectType":
return { ...state, ProjectType: action.payload };
case "SAVE_ProjectTypeAll":
return { ...state, ProjectTypeAll: action.payload };
case "SAVE_Project":
return { ...state, Project: action.payload };
default:
return state;
}
};
```
* #### store:資料中心,整合所有 Reducer,每個專案只能有一個 store,並且可以透過 dispatcher 來更新 state。
```javascript=
const projectMiddlewares = [pet, thunk];
const store = createStore(
reducers,
compose(
applyMiddleware(
...projectMiddlewares,
)
)
);
```

1. 使用者操作畫面觸發事件,發送action
2. action透過dispatcher傳送至middlewares以及store
3. middlewares呼叫對應的API,store向reducer調用對應state
4. middlewares將API回傳的結果透過dispatcher傳送給reducer
5. reducer更新state的值
6. store接收到state的值有變動重新渲染元件
## Redux-Saga
解決了redux 非同步的問題,並且程式可讀性較佳。

1. 使用者操作畫面觸發事件發送至saga
2. saga呼叫對應的API,並等待API的回傳結果
3. 將結果透過dispatcher傳送給store
4. store向reducer調用對應state
5. reducer更新state的值
6. store接收到state的值有變動重新渲染元件
```javascript=
import { put, takeLatest, call, all } from "redux-saga/effects";
import { GET_API} from "../services/api";
import { handleError } from "../utils/error";
function* GET_APIEffect({ payload, callback }) {
try {
const Result = yield call(GET_API, payload);
yield put({ type: "SAVE_API", payload: Result });
if (callback) callback();
} catch (error) {
yield handleError(error);
}
}
```