在Next/react裡,元件間的資料主要是靠props來傳遞,然而,當元件越來越多的時候,這樣的傳遞就會過於複雜,這時候就可以利用context來分享資料。在Material-UI裡,會使用ThemeProvider,ThemeProvider就是利用context。當然,也可以使用更複雜的Redux/Recoil來達成這樣的效果,不過,多數的情況下,Context就能解決問題了。在Context裡,有三個基本概念:首先,透過createContext產生一個context,接下來,利用context.Provider指定使用的範圍,透過useContext取得context。
先利用createContext,產生一個context
/components/context/UserContext.jsx
export const UserContext = React.createContext({
username: "testing",
});
如果希望整個專案都可以取得context內容,在Next.js裡,就是修改_App.tsx/_App.js,在<Component />之外,加上<UserContext.Provider>,就會讓全部的元件都可以取得UserContext的內容。
import '../styles/globals.css'
import type { AppProps } from 'next/app'
**import { UserContext } from '@/components/context/UserContext';**
function MyApp({ Component, pageProps }: AppProps) {
return (
**<UserContext.Provider value={{ username: "test" }}>**
<Component {...pageProps} />
**</UserContext.Provider>**
)
}
export default MyApp
想取得內容時,可利用useContext取得內容,注意,內容會是”Hello, test”,而不是”Hello, testing”,因為我們透過Provider改寫了值。
import { useContext } from 'react';
import { UserContext } from '@/components/context/UserContext';
export default function Home() {
const user = useContext(UserContext);
return (
<div>Hello, {user.username}</div>
)
}
我們先修改一下
/components/context/UserContext.jsx
import React, { useState, useEffect } from "react";
import { getApps, initializeApp } from "firebase/app";
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { firebaseConfig } from "@/settings/firebaseConfig";
export const UserContext = React.createContext();
export function UserProvider({ children }) {
const user = useFirebaseAuth();
return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}
export default function useFirebaseAuth() {
const [currentUser, setCurrentUser] = useState(null);
if (getApps().length === 0) {
initializeApp(firebaseConfig);
}
const auth = getAuth();
useEffect(() => {
const unsub = onAuthStateChanged(auth, (user) => {
if (!user) {
setCurrentUser(null);
return;
}
setCurrentUser(user);
console.log(user);
});
return () => {
unsub();
};
}, [auth]);
return currentUser;
}
因為我們在UserContext裡寫了一個UserProvider,所以,_App.tsx就可以改成:
import '../styles/globals.css'
import type { AppProps } from 'next/app'
**import { UserContext } from '@/components/context/UserContext';**
function MyApp({ Component, pageProps }: AppProps) {
return (
**<UserProvider>**
<Component {...pageProps} />
**</UserProvider>**
)
}
export default MyApp
使用時就可以直接取得利用getAuth()所取得的資料,例如:
import { useContext } from 'react';
import { UserContext } from '@/components/context/UserContext';
export default function Home() {
const user = useContext(UserContext);
console.log('user', user)
return (
<div>Hello, {user && user.displayName}</div>
)
}