---
# System prepended metadata

title: React.js Hook 入門 - 4. useContext
tags: [React, TypeScript, Hook]

---

# React.js Hook 入門 - 4. useContext
###### tags: `React` `Hook` `TypeScript`

## 簡介
> Context provides a way to pass data through the component tree without having to pass props down manually at every level.

有別於一般透過參數一層一層傳遞的方式，Context 提供了另一種方式，透過 component tree 傳遞資料。

以往我們在開發時，為了追求更好的可讀性與維護性，通常都會將 component 拆小，但相對的就會有更多的機會需要在不同的 component 間傳遞參數。

在不同的 component 傳遞參數是蠻常會遇到的情況，偶而會有需要傳遞多層的情況發生。通常傳遞多層是我們不想面臨的情況，使用 Context 可以讓我們優雅地解決這個問題。

### 何時使用 Context
Context 設計的宗旨就是共享資料，就像是全域的變數一樣。當你的資料需要被多個 component 使用時，使用 Context 就是個很好的解法 (ex. 使用者的資料、網站的語系、樣式)。

## useContext 的用法
#### Step 1 - 建立 user context
user-context.ts
```typescript=
import React, { useState } from 'react'

export type User = {
    id: string
    name: string
    age: number
}

type UserProps = {
    user: User | undefined
    setUser: React.Dispatch<React.SetStateAction<User | undefined>>
}

const [user, setUser] = useState<User>()
const props: UserProps = {
    user,
    setUser
}

export const UserContext = React.createContext(props)
```

#### Step 2 - 建立 user component

user.tsx
```typescript=
import React, { useContext } from 'react'
import { UserContext } from './user-context'

const User = () => {
    const { user } = useContext(UserContext)
    
    return (
        <div>{`Hi, I am ${user.name}, and I am ${user.age} years old.`}</div>
    )
  }
}

export default User
```

#### Step 3 於最底層建立 Context Provider，並將值傳入

app.tsx
```typescript=
import React, { useEffect, useState } from 'react'
import { UserContext, User } from './user-context'
import User from '.user'

class App extends React.Component {
    const [user, setUser] = useState<User>()

    useEffect(() => {
        signIn()
    }, [])
    
    const signIn = () => {
        setUser({
            id: '001',
            name: 'Andy',
            age: 18
        })
    }

  render() {
    return (
      <Page>
        <UserContext.Provider value={{user, setUser}}>
          <User />
        </UserContext.Provider>
      </Page>
    );
  }
}

ReactDOM.render(<App />, document.root);
```

透過使用 Context，我們在 render User Component 時不需將 user 透過參數傳入，只要在 user component 裡面使用 useContext 就能直接取得，相當方便。

### 小結
官網中有提到，若只是要避免在多層中傳遞 props，可以使用 component composition。Context Hook 最核心的精神還是讓你能在多個 component 中共用資料，這兩者還是有些許的差別。

##### Reference
[Context](https://zh-hant.reactjs.org/docs/context.html)