---
# System prepended metadata

title: 從 Hooks 開始，讓你的網頁 React 起來系列的閱讀筆記（23-30 完）
tags: [React, 閱讀筆記, 前端筆記]

---

# 從 Hooks 開始，讓你的網頁 React 起來系列的閱讀筆記（23-30 完）
###### tags: `閱讀筆記` `前端筆記` `React`
## 完成章節

- 23-25（2021/11/29）
- 25-30（2021/11/30）

## 要看清楚 `async/await` 並沒有執行

`useCallback` 是回傳第一個參數（函式），如果 `useCallback` 第一個參數是匿名函式，那麼就會回傳該匿名函式。

初次渲染（firs）的執行順序：
first render component => `useCallback()` 得到的函式儲存在 `fetchData` => `useEffect` => 執行 `fetchData` => 觸發 `useState` => 叫用 `fetchingData`（打 API）資料 => `fetchData` 內的 `useState` re-render => `fetchingData` 取得 API 回應，執行 `useState` => 執行 `useState` 的 re-render
==共 render 三次==

手動點擊觸發事件的執行順序：
`onClick` 觸發 `fetchData` => 執行 `fetchData` 更新 `state` 觸發 `useState` => 叫用 `fetchingData`（打 API）資料 => `fetchData` 內的 `useState` re-render => `fetchingData` 取得 API 回應，執行 `useState` => 執行 `useState` 的 re-render
==共 render 兩次==


![](https://i.imgur.com/2MfVNDa.png)


```javascript=
// WeatherApp.js

// ...

 const fetchData = useCallback(() => {
	// 只是先宣告函式
    async function fetchingData() {
      console.log("fetch data");
      const [currentWeather, weatherForecast] = await Promise.all([
        fetchCurrentWeather(),
        fetchWeatherForecast()
      ]);
      setWeatherElement({
        ...currentWeather,
        ...weatherForecast,
        isLoading: false
      });
    }

	// 所以這邊的 setSometing 會先被執行，並執行 re-render
    setWeatherElement((prevState) => {
      return {
        ...prevState,
        isLoading: true
      };
    });
    
	// fetchingData 到這邊才被叫用
	// 即時 fetchingData 也被叫用，但是因為還要等資料回傳，所以就會先執行上方 setSometing 後的 re-render
    fetchingData();
  }, []);

// console.log(fetchData);
// () => {    async function fetchingData() { ... } }

  useEffect(() => {
    console.log("Hi from useEffect in WeatherApp");
    fetchData();
  }, [fetchData]);

// ...
```

### 為什麼要在 `onClick`（觸發拉去 API）之間先執行 `useState` 更改 `isLoading` 的值？

回顧上面的順序就會發現 `isLoading` 在拉完 API 就變成 `false` 了，為了讓手動點擊更新資料時畫面還可以顯示「正在拉取資料」，在非同步的等待 API 得到回應時先重新更新 `state`（`isLoading: true`），因為這樣子會更新頁面，所以可以達到顯示「正在載入」的頁面效果。

## 此系列文章學到了什麼？

### 1. 基本的 JSX 運用

因為 JSX 支援表達式（Expression）所以陳述式的 `forEach` 迴圈沒辦法使用，就要靠其他陣列的的方法（比方來說 `Array.map()`）執行迴圈的事情（重複新增相同的 Components）。
除此之外，因為 `if` 也是陳述式（Statement）所以在 JSX 中也沒辦法使用，這個時候就必須使用三元運算子或者邏輯運算子達到「特定情況」執行特定任務的目標。

```javascript=
// 基本的 if 判斷

const i = 1;
if (i === 1) { console.log('Hi!'); }
else { console.log('Hello!'); }

// 使用三元運算子

i === 1 ? console.log('Hi1') : console.log('Hello!')
```

```javascript=
// 使用邏輯運算子達到 render 特定的 component

// ....

// && 如果前面的是 true 的話就會回傳 && 後面的
// => 所以在 && 前面寫判斷，如果 && 前判斷為 true 的話就會回傳 && 後面的東西（也就是要 render 的 component）
return (
  {currentPage === 'Setting' && ( // another component)}
)
```

### 2. 鑑識複雜的資料該如何整理

從 PJ 因為 API 的格式混亂運用 `Array.reduce()` 整理資料學習適用的整理資料技巧，也看到 PJ 用物件整理相同的資料再用 `Array.find()` 找到需要的物件（每個物件都有提供搜尋的 value，所以只要搜尋到該 value 就會得到整包需要的物件）。

### 3. 要更換頁面的話由 `state` 控制

==由 `state` 提供的函式（`setSometing`）更換初始值，並切 re-render（達到頁面更新）==，所以一切都要以 `state` 為核心思考，要找出主要的 `state` 在哪裡（關鍵字： React 是單向流傳資料，由高的 Component 流傳資料到低的 Component）（如同 Function Scope 往外找），找到主要的 `state` 就可以把資料透過 `props` 的方式傳遞任何東西（物件、字串或者函式等等...）。
為了幫助自己建構 Component 的分級，可以先問自己幾個問題幫助切分 Component 的關聯：

1. 這個資料可以透過 `props` 傳下來嗎？（是的話就不用 `state`）
2. 這個資料需要一直更動嗎？（否的話就不用 `state`，因為根本沒有更新的必要）
3. 使用 `state` 時要想要如何使用「最少」的 `state` 達到同樣的效果

### 4. 找到主要的 Component 再分配 `props` = 好的結構

==找到主要的 Component 很重要。==

![](https://i.imgur.com/hV2J2we.png)
[*PJ react 教學 - 專案 component 整理*](https://whimsical.com/pj-react-component-7qXfVitcispT7srgMQtAxF)

## 參考資料
1. [從 Hooks 開始，讓你的網頁 React 起來 23-30](https://ithelp.ithome.com.tw/users/20103315/ironman/2668)
2. [用 React 思考](https://zh-hant.reactjs.org/docs/thinking-in-react.html)

