0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ログイン情報をContextで、どのコンポーネントからでも取得する方法

Posted at

注意

あらかじめ言っておきますが、筆者は初心者なので、自分なりの解釈でまとめています。「100%信じるぜ!」という気持ちで読まないようお願いします。どうぞよろしく!

参考

経緯

ポートフォリオ用のアプリを作成しているのですが、ログイン情報をどのコンポーネントからも取得したかったので、その際にcontextを使用したので、備忘録として残しておくことにしました。

私が作成したアプリは、layout.tsxでログイン情報を取得し、<Header user_data={user_data}></Header> これで、Headerにpropsとして渡しておりました。
しかし、深いコンポーネントでもログイン情報を取得する必要があったので、propsで渡すと、コードが冗長になるよなぁと考えました。そこで、contextを使用するとpropsで渡す必要がないということがわかったので、今回使用することとしました。

使用技術

・typescript
・nextjs
・supabase

今回のコード

layout.tsx
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があります。

RecipeCreation.tsx
const RecipeCreation = () => {

return(
    <div>
        ここにユーザー情報を表示したい
    </div>
)}

用語の意味

コンテクスト

今回説明する内容です

引用:React公式リファレンスより
コンテクスト:props 受け渡しの代替手段 。propsのバケツリレーを防ぐ。

プロバイダー

コンテクストの値を提供するもの
プロバイダーで囲まれたコンポーネントのコンテクストを使用することができます

使用方法

1.コンテクストを作成する(箱を作成する)

UserContext

type UserContextType = {
    email:string
} | null

export const UserContext = createContext<UserContextType>(null);

2.プロバイダーを作成する

UserContext.tsx
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.プロバイダでアプリ全体を囲む

layout.tsx
  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を呼び出せます。

RecipeCreation.tsx
import { UserContext } from '@/context/UserContext'

const RecipeCreation = () => {
  const userEmail = useContext(UserContext)

  return (
    <div>
      ここにユーザー情報を表示したい
    </div>
  )
}

5.ログイン情報を表示する。

RecipeCreation.tsx
const RecipeCreation = () => {
return(
    <div>
        //ここにユーザー情報を表示したい
        {userEmail?.email}
    </div>
)}

感想

すこし複雑でわかりにくい気がしますが、じっくり考えれば、使えます!
Reduxを使用するより簡単なので、いいですね。
ガンガン開発していこう!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?