---
# System prepended metadata

title: '[Udemy - React] 課程流程筆記（sec. 18）'
tags: [React, Udemy 課程筆記, 前端筆記]

---

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