2023.10.23
現在如果使用 Vue 開發網站,我會習慣用 Vite + Pinia 幫我實現狀態管理與跨組件傳值的功能。
至於 React 也有蠻多選擇,較知名的是 Redux,以下是幾個常見的 Library:
connect
高階元件來連接 React 元件。Redux 較適用於大型應用。因為我的需求非常簡單,只是要跨組件傳遞會員資料,不需要用到狀態管理,因此我選擇的方法是「React Context API」,不需要額外安裝套件,直接使用 React API 即可。
實作的功能與流程為:使用者切換路由時,都會先打一隻 /me
的 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> ) }
▼ 打開 App.jsx,匯入 UserProvider
import { UserProvider } from './context/UserContext' const App = () => { return ( // 使用 UserProvider,跨組件傳遞 user 資料 <UserProvider> <AppContent /> </UserProvider> ) }
▼ 我們可以用剛剛的 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 資料 ) }
假設我們有一頁 Home.jsx 也要讀取使用者資料,只要使用 useUser
就能輕鬆取得
import { useUser } from './context/UserContext' const Home = () => { const user = useUser() return ( // 處理並渲染 user 資料 ) }
寫法就跟前面一樣,方便易懂好上手。
如果只是想要單純傳值,不需要複雜的狀態管理,可以考慮使用內建的 Context API,簡單解決煩惱!