注意
あらかじめ言っておきますが、筆者は初心者なので、自分なりの解釈でまとめています。「100%信じるぜ!」という気持ちで読まないようお願いします。どうぞよろしく!
参考
経緯
ポートフォリオ用のアプリを作成しているのですが、ログイン情報をどのコンポーネントからも取得したかったので、その際にcontextを使用したので、備忘録として残しておくことにしました。
私が作成したアプリは、layout.tsxでログイン情報を取得し、<Header user_data={user_data}></Header>
これで、Headerにpropsとして渡しておりました。
しかし、深いコンポーネントでもログイン情報を取得する必要があったので、propsで渡すと、コードが冗長になるよなぁと考えました。そこで、context
を使用するとpropsで渡す必要がないということがわかったので、今回使用することとしました。
使用技術
・typescript
・nextjs
・supabase
今回のコード
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
//今回supabaseより、user情報を取得しました。
const supabase = await createClient()
const { data, error } = await supabase.auth.getUser()
const user_metadata = data.user?.user_metadata as UserMetadata
const user_data : {email:string|null} = {
email:user_metadata?.email
}
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased flex w-screen`}>
<Sidebar></Sidebar>
<div className="grow bg-white m-2 rounded-2xl h-screen flex flex-col">
<Header user_data={user_data}></Header>
{children}
</div>
</body>
</html>
);
}
layout
配下に以下のRecipeCreation.tsx
があります。
const RecipeCreation = () => {
return(
<div>
ここにユーザー情報を表示したい
</div>
)}
用語の意味
コンテクスト
今回説明する内容です
引用:React公式リファレンスより
コンテクスト:props 受け渡しの代替手段 。propsのバケツリレーを防ぐ。
プロバイダー
コンテクストの値を提供するもの
プロバイダーで囲まれたコンポーネントのコンテクストを使用することができます
使用方法
1.コンテクストを作成する(箱を作成する)
type UserContextType = {
email:string
} | null
export const UserContext = createContext<UserContextType>(null);
2.プロバイダーを作成する
export const UserProvider = ({ children }: { children: React.ReactNode }) => {
const [userEmail, setUserEmail] = useState<UserContextType>(null)
//ユーザー情報を取得する
useEffect(() => {
const fetchUser = async () => {
const supabase = createClient()
const { data } = await supabase.auth.getUser()
const email = data.user?.user_metadata?.email ?? null
setUserEmail({ email })
}
fetchUser()
}, [])
return (
<UserContext.Provider value={userEmail}>
{children}
</UserContext.Provider>
)
}
以下を返すことにより、「UserContext
の値はuserEmail
ですよ」というプロバイダとなります
<UserContext.Provider value={userEmail}>
{children}
</UserContext.Provider>
children
とすることで、UserProvider
で囲まれた、コンポーネントがUserContext
を呼び出すことにより、ユーザー情報を取得することができます、
3.プロバイダでアプリ全体を囲む
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased flex w-screen`}>
<UserProvider>
<Sidebar></Sidebar>
<div className="grow bg-white m-2 rounded-2xl h-screen flex flex-col">
<Header></Header>
{children}
</div>
</UserProvider>
</body>
</html>
);
4.useContext
でコンテクストを使用する
Contextを受け取りたいコンポーネントでuseContext
を使用することでContextを呼び出せます。
import { UserContext } from '@/context/UserContext'
const RecipeCreation = () => {
const userEmail = useContext(UserContext)
return (
<div>
ここにユーザー情報を表示したい
</div>
)
}
5.ログイン情報を表示する。
const RecipeCreation = () => {
return(
<div>
//ここにユーザー情報を表示したい
{userEmail?.email}
</div>
)}
感想
すこし複雑でわかりにくい気がしますが、じっくり考えれば、使えます!
Reduxを使用するより簡単なので、いいですね。
ガンガン開発していこう!