# [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.

(可以只有一個 reducer)

(如果有多個 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