iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
自我挑戰組

React 30 天學習歷程系列 第 25

【Day 25】React Hook(二): Context 和 useContext

Context

在介紹 useContext 之前,得先介紹 ContextContext是 React 用來處理資料全域共享的一個 API,它還可以避免需要多層傳遞 props 的情況,或是元件之間沒有上下層關係的情況。使用 Context 主要是透過以下幾個步驟

  1. 我們在根元件的位置(例如 App.js)透過 React.createContext() 創建 Context 物件。React.createContext() 裡面可以傳遞參數。
const Context = React.createContext() 
  1. 我們創建的這個 Context 上面會有一個 Provider 元件,接著我們就使用 Context.Provider 來包覆元件,並傳遞一個 value。我們先將資料透過 value 傳遞給 ProviderProvider 再將資料傳給裡面的元件,如 TestComponent1TestComponent2。下面的例子中,建立 Context 的根元件是 UserProfile
const Context = React.createContext({ count: 1 }) 

class UserProfile extends React.Component {

    state = {
        count: 0
    }

    render() {
        return (
            <div>
                <Context.Provider value={ this.state.count }>
                    <TestComponent1 />
                    <TestComponent2 />
                </Context.Provider>
            </div>
        );
    }
}
  1. 在根元件下的元件中,可以透過 Context.Consumer 獲得 Context 共享的資料。
// TestComponent1 元件
class TestComponent1 extends React.Component {
    render () {
        return <Context.Consumer>
            {count => <div> { count } </div>}
        </Context.Consumer>
    }
}

// TestComponent2 元件
class TestComponent2 extends React.Component {
    render () {
        return <Context.Consumer>
            {count =>  <button onClick={ count => count + 1}>count++</button>}
        </Context.Consumer>
    }
}

不過這種在元件內直接建立 Context 的方式,容易造成元件比較混亂,所以通常會在獨立的檔案中建立 Context,之後再由根元件調用,後面將會有範例。需要注意的是,盡量一個 Context 只給一個狀態,不要包裝太多狀態,會讓狀態不好管理。

useContext(Context)

useContext(Context) 基本上就是為了讓我們使用 Context 所提出的 API,它接受 React.createContext() 的返回值作為參數,返回最新的 Context。另外,使用 useContext(context) 就不用再去使用 ProviderConsumer。例如下面的範例,我們透過 React.createContext() 建立資料後,就可以賦給 Context,之後再利用 useContext(Context) 在元件中調用 Context 就可以拿到裡面的資料。

const Context = React.createContext({ loading: false, name: 'leo'})

// 元件 1
const TestComponentOne = () => {
    const context = useContext(Context)
    
    return <div>
        { context.loading && 'loading...' }
    </div>
}

// 元件 2
const TestComponentTwo = () => {
    const context = useContext(Context)
    
    return <div>
        { context.name && context.name }
    </div>
}

我們也可以利用直接 export Context 的方式來傳遞,如下

export const Context = React.createContext({ loading: false, name: 'leo'})

然後在元件內 import

import { Context } from './index'

const TestComponentOne = () => {
    const context = useContext(Context)
    
    return <div>
        { context.loading && 'loading...' }
    </div>
}

不過,這種做法並不是比較好的方法。比較好的方式是建立一個單獨的模組來封裝 Context。我們在 src 內創建一個 store 資料夾並建立一支 index.js 檔,將 Context 移到裡面,如下

import React from 'react'

const Context = React.createContext({ loading: false, name: 'leo'})

export default Context

然後在其他元件引入

import Context from '../../store'

const TestComponentOne = () => {
    const context = useContext(Context)
    
    return <div>
        { context.loading && 'loading...' }
    </div>
}

參考資料

上下文(Context)
[React] React Context API 以及 useContext Hook 的使用


上一篇
【Day 24】React Hook(一): Hook 簡介 及 useState、useEffect 使用
下一篇
【Day 26】React Hook(三): useReducer
系列文
React 30 天學習歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
yanzhong
iT邦新手 4 級 ‧ 2021-01-08 16:21:07

這麼好的文章,希望更多人看到!!!
大大解釋得很清楚
原本對於useContext是一竅不通,但是看到const context= useContext(Context)這邊,
直接了解。

我要留言

立即登入留言