LoginSignup
4
1

More than 1 year has passed since last update.

【Gatsby.js, React】ページ遷移させたいときは navigate() を使う

Last updated at Posted at 2021-02-23

こんにちは、ndj です。

現在、勉強がてら Gatsby.js を使用して簡単なホームページを作成しています。
ヘッダーに言語を選択できる select ボックスを作成して、選択した言語に合わせてページを遷移したいなと思ったのですが、ハマってしまったので備忘録として残しておきます。

(2021/03/01) 追記:navigate を使用する場合は、Router を使用しなくてもよいことがわかったので、「this.props.history.push ではなく、navigate() を使用する」のコード部分を修正。

使用技術とバージョン情報

  • gatsby: 2.32.3
  • gatsby-source-microcms: 1.0.1
  • react-router-dom: 5.2.0
  • react: 16.12.0

結論

  • React 標準で使用される、this.props.history.push ではなく、gatsbynavigate() を使用する。

やりたかったこと

amazon など、グローバルに使用されているサービスってヘッダーに言語情報を選択できるようになっていますよね。

スクリーンショット 2021-02-23 231313.png

amazon みたいに、言語情報を選択したら、その言語のページに遷移できるようにしたいなと。

試みたこと

当初は、以下のように、 <select>タグ の onChange イベントハンドラで this.props.history.push(e.target.value) をして、ページを遷移しようとしていました。
参考:codesandbox.io: w031p82nr5

また、言語別の説明文は headlessCMS に保存しており、ページ生成の際に、gatsby-node.jscreatePage<Home /> に context を渡す。みたいな感じでページを生成しておりました。

header.js
import React from 'react';
import { useStaticQuery, Link, navigate } from 'gatsby';
import { Switch, Route, BrowserRouter as Router, withRouter } from 'react-router-dom';
import Home from '../pages/locale';

class DropDown extends React.Component {
    onChange = (e) => {
        this.props.history.push(`/${e.target.value}`);
    }
    render() {
        return (
          <select onChange={this.onChange}>
            <option value="ja">日本語</option>
            <option value="en">English</option>
          </select>
        );
    }
}

const Menu = withRouter(DropDown);

export default function Header() {
    return (
        <Router>
            <header className="header">
                <nav>
                    <ul id="header-list">
                        <li>
                            <Menu />
                        </li>
                        <li>
                            <Link to="/">Install now</Link>
                        </li>
                    </ul>
                </nav>

            </header>

            <Switch>
                <Route path='/ja' render={() => <Home locale="ja" />} />
                <Route path='/en' render={() => <Home locale="en" />} />
            </Switch>
        </Router>

    );
}

こんな感じでページ遷移を実現させたかったんですが、エラーが出る。。。

Uncaught TypeError: Cannot read property 'post' of undefined

原因っぽい部分

エラー自体の原因は、以下の部分です。

error.jsx
<Route path='/ja' render={() => <Home locale="ja" />} />

先述のように、言語別の説明文は headlessCMS に保存しており、ページ生成の際に、gatsby-node.jscreatePageGraphQL query を投げて、 <Home /> に context を渡す。みたいな感じでページを生成しておりました。
つまり、上記のコードだと select ボックスの選択肢が変化したときに context を渡せないので、エラーが出てたという感じです。

なので、ページ遷移の方法を工夫する必要がありそうです。

this.props.history.push ではなく、navigate() を使用する

DropDownonChange の部分を以下のように変更します。
gatsby に専用の function があるみたいです。
参考:gatsbyjs:How to use the navigate helper function
参考:stackoverflow: What's the equivalent of this.props.history.push in gatsby?

header.js
import { Link, navigate } from 'gatsby';

class DropDown extends React.Component {
    onChange = (e) => {
        navigate(`/${e.target.value}`);
    }
    render() {
        return (
          <select onChange={this.onChange}>
            <option value="ja">日本語</option>
            <option value="en">English</option>
          </select>
        );
    }
}

export default function Header() {
    return (
        <React.Fragment>
            <header className="header">
                <nav>
                    <ul id="header-list">
                        <li>
                            <DropDown />
                        </li>
                        <li>
                            <Link to="/">Install now</Link>
                        </li>
                    </ul>
                </nav>
            </header>
        </React.Fragment>

    );
}

最後に

gatsby もさることながら、 React 自体の習熟度も低く解決に時間がかかってしまいましたが、コツコツやっていきたいと思います。
また、今回解決方法を検索する際に積極的に英語のページを見るようにしましたが、翻訳機能様の存在とソースは全世界で共通なので頑張れば意外といけました。

誤字脱字、技術的なご指摘などございましたら、コメントいただけますとありがたいです。
ここまで読んでいただきありがとうございました。
これからも巨人の肩に乗り続けます。

参考

amazon
codesandbox.io: w031p82nr5
gatsbyjs:How to use the navigate helper function
stackoverflow: What's the equivalent of this.props.history.push in gatsby?

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1