# useContext 常犯錯誤與如何在 TS 使用
<iframe width="560" height="315" src="https://www.youtube.com/embed/I7dwJxGuGYQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
:::spoiler 目錄
[TOC]
:::
## TL;DR
- 在使用 useContext 時,一定要將其包裝成 custom hook
- [React 官方文件新增了 TypeScript 使用專文](https://react.dev/learn/typescript?fbclid=IwAR3Pgkr8xpS48Vwa0ADo3oagaAPKX1q05jHhtbXH8ltV8MKwa8FAvePoXPU)
- [英文版本](https://jason60810.hashnode.dev/always-use-a-custom-hook-for-context-api-not-usecontext-react-context-api-typescript)
## 資料夾結構 ( 使用 next app route )

### theme-context.tsx
一定要加上 `use client`,因為 useState 只能在 client component 運作 ,
**特別注意,就算這裡加了`use client`,所有的子層還是 server component (預設)**

### layout.tsx
加上 provider 之後,下面所有的子層都可以拿到值,不用用 prop 一個一個傳下去

### page.tsx

### logo.tsx
1. 因為 useContext 要在 client component 運作,所以要加上 `use client`。
2. 當使用 useContext 時,一定要引入 ThemeContext,用起來很麻煩
3. 因為 ThemeContext 預設是 null,所以當不是在 provider 裡使用 `useContext` 時 ( Logo component ),會發生錯誤,因此需要先確認有 context

舉例:不是在 provider 裡使用 `useContext`

### 創建 custom hook

### 使用 custom hook
現在引入 ThemeContext 和處理錯誤的問題,已經抽離到 custom hook 中

### 加上型別
1. React.ReactNode,可以接受 JavaScript primitives ,如果只想要是 jsx 可以使用 React.ReactElement ( [react 官方文件](https://react.dev/learn/typescript#typing-children) )
2. `type Theme` 可以讓 `useState` 在 get 和 set 時,可以使用正確的型別,例如:當想要 `setTheme('blue')` 時,會報錯,因為 `type Theme` 只有 'dark' 和 'light'
3. 在給予 createContext 型別時,可以利用 ts 的 union 讓 createContext 知道可能有 null 這個型別 ( [react 官方文件](https://react.dev/learn/typescript#typing-usecontext) )
