/
CATEGORY
React
/
用 React Context API 實作跨組件傳值的功能

用 React Context API 實作跨組件傳值的功能

MUKI AI Summary

使用 React Context API 可以輕鬆實現跨組件傳值功能,適合不需要複雜狀態管理的小型應用。與 Vue 的 Vite + Pinia 類似,React 提供多種狀態管理選擇,如 Redux、Mobx、Zustand、Recoil 和 Jotai,其中 Context API 是內建的選項,無需額外安裝套件。本文介紹了如何在 React 中利用 Context API 來傳遞會員資料,通過建立 UserContext 並在 App 中使用 UserProvider 來共享資料,確保在不同組件間能夠輕鬆取得使用者資料。

實作過程包括在獨立的 context 檔案中打 API 取得即時會員資料,並使用 createContext 和 useContext 建立資料共享機制。在 App 組件中引入 UserProvider,然後在內部使用 useUser Hook 來讀取和渲染使用者資料。此外,其他頁面如 Home.jsx 也可以通過 useUser 獲取資料,實現簡單而有效的跨組件資料傳遞。這種方法適合需要跨組件傳遞資料但不需要複雜狀態管理的情況。...

需求

現在如果使用 Vue 開發網站,我會習慣用 Vite + Pinia 幫我實現狀態管理與跨組件傳值的功能。

至於 React 也有蠻多選擇,較知名的是 Redux,以下是幾個常見的 Library:

  • Redux
    Redux 是一個非常流行的狀態管理 Library,用於管理應用的全域狀態。你可以將應用的狀態儲存在一個全域儲存中,並通過 connect 高階元件來連接 React 元件。Redux 較適用於大型應用。
  • Mobx
    Mobx 是另一個流行的狀態管理庫,它使用可觀察對象和響應式機制來管理狀態。它可以更簡單地實現狀態管理,適用於中小型應用。
  • React Context API
    React 內建的 Context API 允許你建立全域的上下文,以便跨元件傳遞資料。雖然它不如 Redux 或 Mobx 強大,但對於小型應用和簡單的跨元件資料傳遞來說非常足夠。
  • Zustand
    Zustand 是一個小巧的狀態管理庫,專門為 React 設計。它使用 Hooks 和 Context API,讓你能夠方便地管理狀態,適用於中小型應用。
  • Recoil
    Recoil 是由 Facebook 開發的狀態管理庫,它專為 React 設計。提供了一種簡單的方式來管理元件之間的狀態,並且支援原子狀態管理。
  • Jotai
    Jotai 是另一個小型的狀態管理庫,使用了 React Hooks 和 Context。它的設計非常簡單,易於理解和使用。(Jotai 是「狀態」的拼音,非常粗暴好理解 😂)

因為我的需求非常簡單,只是要跨組件傳遞會員資料,不需要用到狀態管理,因此我選擇的方法是「React Context API」,不需要額外安裝套件,直接使用 React API 即可。

實作的功能與流程為:使用者切換路由時,都會先打一隻 /me 的 api 取得即時的會員資料與權限,我再用這些資料,顯示會員基本資料以及做權限控管。

使用 Context API 建立資料

首先,我們要把「打 /me API」這件事情,放在一個獨立的 context 檔案中

▼ 先新增檔案:src/context/UserContext.js,再用 crateContext 以及 useContext 建立並儲存資料

import React, { createContext, useContext, useState, useEffect } from 'react'
import { getUserApi } from '../api/auths'

const UserContext = createContext()

export const useUser = () => {
  return useContext(UserContext)
}

export const UserProvider = ({ children }) => {
  const [loading, setLoading] = useState(true)
  const [user, setUser] = useState({})

  useEffect(() => {
    async function fetchUser() {
      try {
        const res = await getUserApi()
        setUser(res.data)
        setLoading(false)
      } catch (error) {
        console.error('Response error:', error)
      }
    }
    fetchUser()
  }, [])

  return (
    <UserContext.Provider value={user}>
      {/* 使用 loading 來判斷是否已經取得使用者資料,如果還沒取得,則不顯示 children */}
      {loading ? null : children}
    </UserContext.Provider>
  )
}

使用 Provider 共享 User 資料

▼ 打開 App.jsx,匯入 UserProvider

import { UserProvider } from './context/UserContext'

const App = () => {
  return (
    // 使用 UserProvider,跨組件傳遞 user 資料
    <UserProvider>
      <AppContent />
    </UserProvider>
  )
}

在 App.jsx 讀取 User 資料

▼ 我們可以用剛剛的 useUser 讀到 User 資料,寫法如下

import { UserProvider, useUser } from './context/UserContext'

const App = () => {
  const user = useUser()
  return (
    <UserProvider>
      // 這邊處理取得的 user 資料
    </UserProvider>
  )
}

但這樣寫 user 會是 undefined,原因是我們在 <UserProvider> 設定之前,就讀取了 useUser,因此 user 為 undefined

▼ 所以比較好的寫法,是在 <UserProvider> 內部使用 useUser Hook,改寫如下

import { UserProvider, useUser } from './context/UserContext'

const App = () => {
  return (
    <UserProvider>
      <AppContent />
    </UserProvider>
  )
}

const AppContent = () => {
  const user = useUser()
  return (
    // 處理並渲染 user 資料
  )
}

在其他頁面讀取 User 資料

假設我們有一頁 Home.jsx 也要讀取使用者資料,只要使用 useUser 就能輕鬆取得

import { useUser } from './context/UserContext'

const Home = () => {
  const user = useUser()
  return (
    // 處理並渲染 user 資料
  )
}

寫法就跟前面一樣,方便易懂好上手。

如果只是想要單純傳值,不需要複雜的狀態管理,可以考慮使用內建的 Context API,簡單解決煩惱!

歡迎給我點鼓勵,讓我知道你來過 :)

12
MUKI says:

如果文章有幫助到你,歡迎分享給更多人知道。文章內容皆為 MUKI 本人的原創文章,我會經常更新文章以及修正錯誤內容,因此轉載時建議保留原出處,避免出現版本不一致或已過時的資訊。

本文地址:https://muki.tw/react-context-api/ 已複製

Subscribe
Notify of
guest

0 則留言
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Copyright © since 2008 MUKI space* / omegaSS theme All Rights Reserved.