# [Udemy - React] 課程流程筆記(sec. 18) ###### tags: `Udemy 課程筆記` `React` `前端筆記` ## Sec 18 ### 233. Providing the Store 為了要讓 React 專案可以使用 redux,必須至專案的入口建立 `<Provider>` ### 234. Using Redux Data in React Components - 使用 `useSelector` 取得 store 的資料 - `useSelector()` 接收一個 callback,其 callback 的 parameter 就是 store ```javascript= // 拿 store 內的 counter const counter = useSelector((store) => store.counter) ``` > Now the great thing is that when you use useSelector React Redux will automatically set up a subscription to the Redux store for this component. > 03:54 使用 `useSelector` 的時候 React 會自動讓該 component 訂閱 store,這樣子當 store 改變時訂閱的 component 就會 re-render > If you would unmount this component React Redux would also automatically clearthe subscription for you. > 04:31 component 被銷毀的時候 React 也會清掉訂閱。 ### 235. Dispatching Actions From Inside Components - `useDispatch()` 用來傳 action 給 store 的 method - 需開一個常數保存 `useDispatch` 回傳的 method,之後便直接使用其常數即可 ```javascript= const dispatch = useDispatch(); dispatch({ type: 'increase' }) ``` ### 237. Attaching Payloads to Actions 就跟之前課程教的 `useReducer` 一樣,`dispatch()` 收的 action 通常會有 `{ type: 用來當作 identifier,供 reducer 判斷要做什麼任務, payload: 外部傳資訊給 reducer 用 }` ```javascript= // STEP 1: 透過 payload 從外部傳資訊給 reducer dispatch({ type: 'increase', payload: { number: 5 } }) const counterReducerFunc = (state, action) => { const { type, payload: { number } } = action; // STEP 2: 實現定義出各種 action 的表 switch(type) { case 'increase': // STEP 3: 透過 payload 讀取外部資訊加總更新 store return { counter: state.counter + number } default: return state; } } ``` ## 238. Working with Multiple State Properties - 在 store 建立一個新的 state 控制是否顯示 `counter` - 同一組 reducer 處理兩個 state(`couter`, `show`) - 切記,`reducer` 必須是 pure function ## 239. How To Work With Redux State Correctly > You should never change the existing state. Instead, always override it by returning a brand new state object. > 02:14 永遠不要改變當前的 state,永遠都使用新的物件複寫舊的 state object ## 240. Redux Challenges & Introducing Redux Toolkit 專案越來越大且複雜時,Redux 可能會越來越難管理,因此 redux-toolkit 就被發明出來了 (比方來說超級多 `type (identifier)` 或者是 reducer 過於肥大等等) ## 241. Adding State Slices - 現在社群主要使用 redux-toolkit(redux 的加強版) - 省略原先 redux 的重複性程式碼 - `createSlice` 建立單組 state group - 需要給 `{ name, initialState, reducers:{ reducerMethods... } }` - 每一個 reducerMethod 可以直接用 mutable 的方式改變值(比如 `todo[index].isCompleted = true`),因為 redux-toolkit 有使用 [Immer](https://immerjs.github.io/immer/) 套件,因此最後會被套件改成 immutable 的寫法 ## 242. Connecting Redux Toolkit State - 原先 `createStore` 改成 `configureStore`(`configureStore` 為 `createStore` 的加強版,目的是 redux-toolkit 為了加強既有 `createStore` 所新增的 ```javascript= import { configureStore } from '@reduxjs/toolkit' export const store = configureStore({ reducer: { counter: counterReducer, }, }) ``` - 每一個透過 `createSlice` 所建立的 `slice` 都有 `.reducer`,這個是一開始呼叫 `createSlice` 傳入 `{ reducers: { reducerMethods... } }` 時集合成的一個 `reducerFunc`(呼叫 `createSlice` 時是建立 reducer 表,最後 redux-toolkit 會幫忙組成一個 `reducerFunc`) > It's basically a big reducer with a couple of if statements that trigger those different reducer methods depending on the action type. ![](https://hackmd.io/_uploads/rJFpdhYYj.png) (可以只有一個 reducer) ![](https://hackmd.io/_uploads/rJZ-tnYKo.png) (如果有多個 reducers,可以丟一個 MAP,redux-toolkit 最後會把多個 reducers 合併成一個大的 reducer) > Behind the scenes configureStore will emerge all those reducers into one big reducer. > 04:02 ## 243. Migrating Everything To Redux Toolkit - 與 react-redux 相同,觸發改變 store 的手段必須由 component 發出,所以就得要找到辦法從 component dispatch action,讓 redux 的 store 可以被更新 - 使用 redux-toolkit 的另一個好處就是不用自己定義一堆 constant action types,因為 redux-toolkit 就會自動生成 type - 需要注意的是:如果想要外部傳資料,傳入的資料外層會先被 `payload: {}` 包起來 ```javascript= dispatch(someAction(10)) // { type: SOME_UNIQUE_IDENTIFIER, payload: 10 } dispatch(someAction({ value: 10 })) // { type: SOME_UNIQUE_IDENTIFIER, payload: { value: 10 } } ``` - `createSlice.actions` 就會將建立 `Slice` 時 `{ reducers: { reducerMethods... } }` 變成各個 action,開發者只要在 component 內 `dispatch(對應的 action)` 就可以直接打出要變更 store 的函式 ```javascript= // 原本是自己定義好表,後續呼叫的時候參照表內的 type 執行任務 const reducerFunc = (state, action) => { const { type } = action; swtich() { ... } } dispatch({ type: '' .... }) // 有了 redux-toolkit 的幫忙,建立表的時候就同時再建立 key,就不用分兩步驟處理 const mySlice = createSlice({ name: ..., initialState: ..., reducers: { increase(state) => { .... } } }) dispatch(increase()) ``` ## 244. Working with Multiple Slices - 目前看起來是一組資料 group 一個 `slice` 並且由自己的 reducer(因為 `createSlice` 時就會一同建立) - 引入其他練習用的 component - 建立另一個 `slice` 負責管理 `auth` state - 因為 `auth` state 需要很多 component 使用,就直接丟到 app-wide