# [第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, ) ) ); ``` ![image](https://hackmd.io/_uploads/BkRE16666.png =580x450) 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 非同步的問題,並且程式可讀性較佳。 ![未命名](https://hackmd.io/_uploads/HJjVxa4Ca.png =590x455) 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); } } ```