
ContextによるグローバルState
Reactで親コンポーネント => 子コンポーネント => 孫コンポーネント の順でpropsを使用すると管理しづらくなるため、ContextによるグローバルStateを使うことがある。
この記事ではContextによるグローバルStateの管理方法について簡単に解説しています。
Viteで前準備
まず、以下のコマンドでVite + React環境を準備します。
npm init vite@latest
プロジェクト名などは以下の通り。
✔ Project name: … vite-react ✔ Select a framework: › React ✔ Select a variant: › JavaScript
準備が完了したらまずmain.jsxを以下に書き換えます。
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render(
<App />
)
次にApp.jsxを以下に書き換えます。
buttonのonClickでContent.jsx => Button.jsxのbuttonのdisabledのfalse, trueが切り替わる処理を書きます。
import { useState } from 'react'
import { Content } from './components/Content'
function App() {
const [isClick, setClick] = useState(false)
const onClickToggle = () => setClick(!isClick)
return (
<>
<button onClick={onClickToggle}>buttonを有効・無効</button>
<Content isClick={isClick}></Content>
</>
)
}
export default App
次にsrc/compornents/Content.jsxを作成します。
import { Button } from './Button'
export const Content = props => {
const { isClick } = props
return (
<>
<Button isClick={isClick} />
</>
)
}
最後にsrc/compornents/Button.jsxを作成します。
export const Button = props => {
const { isClick } = props
return (
<button disabled={!isClick}>button</button>
)
}
これでnpm run dev (npm run build)を実行すると以下のようなSPAが作成されます。
これでも動作するが、親 (App) => 子 (Content) => 孫 (Button)の過程でpropsが複数使用されているので、グローバルStateの管理に変更する。
providersを作成
src/component/providers/ButtonProvider.jsxを作成してcreateContextとuseStateをimportして使用するコードを作成する。
import { createContext, useState } from 'react'
export const ButtonContext = createContext({})
export const ButtonProvider = (props) => {
const { children } = props
const [isClick, setClick] = useState(false)
return (
<ButtonContext.Provider value={{isClick, setClick}}>
{children}
</ButtonContext.Provider>
)
}
次にmain.jsxでButtonProviderをimportして<App />を囲む。
これで<App />内は何階層でもpropsではなくContextによるグローバルStateから値を受け取れる。
import ReactDOM from 'react-dom/client'
import App from './App'
import { ButtonProvider } from './components/providers/ButtonProvider'
ReactDOM.createRoot(document.getElementById('root')).render(
<ButtonProvider>
<App />
</ButtonProvider>
)
次にApp.jsxのuseStateをuseContextに書き換えて、ButtonContextをimportしてuseContextでisClickとsetClickに代入する。
代入時のconst部分が[]ではなく{}になっているので注意。
const [isClick, setClick] = useState(false) ↓ const {isClick, setClick} = useContext(ButtonContext)
import { useContext } from 'react'
import { ButtonContext } from './components/providers/ButtonProvider'
import { Content } from './components/Content'
function App() {
const {isClick, setClick} = useContext(ButtonContext)
const onClickToggle = () => setClick(!isClick)
return (
<>
<button onClick={onClickToggle}>buttonを有効・無効</button>
<Content isClick={isClick}></Content>
</>
)
}
export default App
次にpropsでContent.jsxからButton.jsxにpropsで渡す必要がなくなったのでContent.jsxのpropsを削除する。
import { Button } from './Button'
export const Content = () => {
return (
<>
<Button />
</>
)
}
最後にButton.jsxでButtonContextをimportしてconst { isClick } = useContext(ButtonContext)で代入すれば完成です。
import { useContext } from 'react'
import { ButtonContext } from './providers/ButtonProvider'
export const Button = () => {
const { isClick } = useContext(ButtonContext)
return (
<button disabled={!isClick}>button</button>
)
}
ReactでContextによるグローバルStateの管理を使用したサンプル