グローバルState
バケツリレーのデメリット
Propsのバケツリレーには以下のデメリットがある。
- Propsが肥大化する
- 本来必要のないPropsを受け取るので、再利用できないコンポーネントになってしまう
- Propsが変更されたら再レンダリングが発生してしまう
ContextでのグローバルState
グローバルStateを管理するライブラリはいくつかあるが、Reactが持っているContext機能を使うことでも実現することができる。
導入手順
- React.createContext()でContextの器を作成
createContext()の引数は{}とする。
引数は初期値となっているが、値はReact.Context.Providerコンポーネントのvalue属性で渡すので通常は初期値が使われることはない。
(React.Context.Providerでラップされていないコンポーネントがコンテキストにアクセスしたときに使われる) - 作成したReact.ContextのReact.Context.ProviderコンポーネントでStateを参照したいコンポーネントを囲む
React.Context.Providerのvalue属性に値を渡す。 - Stateを参照したいコンポーネントでReact.useContext()を使う
プロバイダーコンポーネント
Contextを保持するためのプロバイダーコンポーネントを作成すると良い。
プロバイダーコンポーネントは何でも囲めるようにPropsとしてchildrenを受け取るようにするのがポイント。
import { createContext } from 'react';
export const AdminFlagContext = createContext({});
export const AdminFlagProvider = ({children}) => {
return (
<AdminFlagContext.Provider value={{name: 'hoge'}}>
{children}
</AdminFlagContext.Provider>
)
}
グローバルStateを参照したいコンポーネントをProviderコンポーネントで囲む
import {AdminFlagProvider} from './components/providers/AdminFlagProvider';
// を追加し、
return (
<AdminFlagProvider>
<Oya/>
</AdminFlagProvider>
);
利用時
import { useContext } from 'react';
import {AdminFlagContext} from './providers/AdminFlagProvider';
//を追加し、
console.log(useContext(AdminFlagContext).name})
ContextにStateを格納する
上記の例では固定値をvalue属性に指定したが、Stateを指定する場合は以下のようになる。
import { createContext, useState } from 'react';
export const AdminFlagContext = createContext({})
export const AdminFlagProvider = ({ children }) => {
const [isAdmin, setIsAdmin] = useState(false)
return (
<AdminFlagContext.Provider value={{ isAdmin, setIsAdmin }}>
{children}
</AdminFlagContext.Provider>
)
}
import { memo, useContext } from 'react';
import {AdminFlagContext} from './providers/AdminFlagProvider';
const Ko = memo(({ resetNum })=>{
console.log('子')
const {isAdmin, setIsAdmin} = useContext(AdminFlagContext)
return (
<>
<h1>子: {isAdmin ? '管理者です' : '管理者以外です'}</h1>
<button onClick={setIsAdmin(!isAdmin)}>切り替え</button>
<button onClick={resetNum}>resetNum</button>
</>
)
})
export default Ko;
コメント