Kohei Blog

夫・父親・医療系エンジニア

GatsbyでuseContextを使う際はgatsby-browserに定義する

GatsbyでuseContextを使ってダークモード対応をした(このブログではない)のですが、useContextのstateの挙動がうまく動かず、見事にハマったのでメモしておきます。

結論から言うと、「公式ドキュメントちゃんと読もう」です。

useContextで発生した問題

こちらの記事を参考に、ダークモードの実装を進めていました(めっちゃ参考になる!) The Quest for the Perfect Dark Mode

Gatsbyの記事ではなく、Reactでダークモード対応する方法だったのですが、Gatsbyもstate使えるし、問題ないだろう。ってことで、そのまま実装。ダークモードの切り替え、localStorageへの保存はうまく行ったのですが、stateの動きがおかしいことに気づきました。

ダークモード切り替え直後に画面遷移すると、dark⇔lightが切り替わってしまう。

  1. TOPページ 初回レンダリング時( dark

  2. TOPページで light へ切り替え

  3. 検索ページへ遷移

  4. 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を介してルート要素をプロバイダーでラップする

  • 公式ドキュメントよむ