GatsbyでuseContextを使う際はgatsby-browserに定義する
GatsbyでuseContextを使ってダークモード対応をした(このブログではない)のですが、useContextのstateの挙動がうまく動かず、見事にハマったのでメモしておきます。
結論から言うと、「公式ドキュメントちゃんと読もう」です。
useContextで発生した問題
こちらの記事を参考に、ダークモードの実装を進めていました(めっちゃ参考になる!) The Quest for the Perfect Dark Mode
Gatsbyの記事ではなく、Reactでダークモード対応する方法だったのですが、Gatsbyもstate使えるし、問題ないだろう。ってことで、そのまま実装。ダークモードの切り替え、localStorageへの保存はうまく行ったのですが、stateの動きがおかしいことに気づきました。
ダークモード切り替え直後に画面遷移すると、dark⇔lightが切り替わってしまう。
-
TOPページ 初回レンダリング時(
dark
) -
TOPページで
light
へ切り替え -
検索ページへ遷移
-
dark
に戻る このときlocalStorageはlight
AppStateはdark
localStorageには保存されているのに、useContextのstateがリセット(というかtoggle)になる謎現象。 Providerがうまく動いてないっぽい?
当時の構成は、/components/templates/Layout/index.tsx
にProviderを読み込ませてchildren
をラップする形でした。
公式ドキュメントを見る
ちゃんと読めば書いてました。
Using React Context API with Gatsby | Modifying the Gatsby Browser file
Next, write the following code within the gatsby-browser.js file, which is in the root folder in a Gatsby project:
gatsby-browser.js
import React from "react"
import { ThemeProvider } from "./src/context/ThemeContext"
export const wrapRootElement = ({ element }) => (
<ThemeProvider>{element}</ThemeProvider>
)
The ThemeProvider component exported from the ThemeContext.js file wraps the root element and is exported as wrapRootElement. This API is then invoked appropriately by the Gatsby API runner.
gatsby-browser.js
にProviderをexportすることでルート要素をラップしてexportされます。 これにより、GatsbyAPIが正常に動作させることができるということ。
まとめ
-
GatsbyでuseContextを使うときは、GatsbyBrowserAPIを介してルート要素をプロバイダーでラップする
-
公式ドキュメントよむ