useContextはReact Hookで提供されています。
これを使うことであるコンポーネントから別のコンポーネントへデータを渡すことができます。
ユーザーセッションなど、グローバルでstateの状態管理をしたい、それぞれのコンポーネントから共通のデータを参照したい時に利用します。
useContextとは
各コンポーネントで共有したいデータがある時や、グローバルなstate管理をしたい時は、useContextを利用することでさまざまなコンポーネントでデータを共有できます。
通常、コンポーネント間のやりとりはpropsを使って親コンポーネントから子コンポーネントへデータを渡します。
useContextは、これを多くのコンポーネントへ渡す時に取り扱いがしやすくなります。
useContextを実装する
useContextを使い、contextで管理するstateや関数を実装します。
DataContext というコンテキストを作成し、DataValuesType型と初期データを定義します。
DataProviderは、childrenを引数にとることでDataProviderの子孫コンポーネントに対してDataValuesTypeの値を渡せるようになります。
useDataContextを用意することで、どこのコンポーネントからでもdataを取得し参照できるように、そしてsetDataでdataを更新できるようにします。
import { DataType, DataValuesType } from '@/types/Data'
import { createContext, useState, useContext } from 'react'
const defaultProvider: DataValuesType = {
data: [],
setData: () => []
}
const DataContext = createContext(defaultProvider)
export function useDataContext() {
return useContext(DataContext)
}
export function DataProvider({ children }: { children: React.ReactNode }) {
const [data, setData] = useState<DataType[]>([])
const value = {
data,
setData
}
return <DataContext.Provider value={value}>{children}</DataContext.Provider>
}
layout.tsxにProviderを追加する
DataProviderを利用することで、その子孫コンポーネントに対してデータを提供できるようにします。
import { DataProvider } from '@/context/DataContext'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang='ja'>
<body>
<DataProvider>
{children}
</DataProvider>
</body>
</html>
}
}
データを取得する
useContextからデータをします。
ここで取得したdataから値を参照します。
また、setDataを利用して、どのコンポーネントからでも、dataを更新することも可能になります。
const { data, setData } = useDataContext()
データを更新する
useContextのsetDataを利用してデータを更新します。
dataは配列が入っているので、既存のdataの追加・更新をsetDataを利用することで可能になります。
setData([...data,[<DataType>])
Summary
データを各コンポーネント間で共有できることは、コードがシンプルで可読性が上がり、状態管理の複雑さを軽減することにつながります。
ただ、何でもかんでもuseContextに持たせると肥大化して可読性の低下、不要なレンダリングの発生の引き金にもなります。
コンポーネントで完結できる状態管理はコンポーネントで管理していきましょう。