LoginSignup
26
18

More than 3 years have passed since last update.

【Next.js】getServerSidePropsでクエリパラメータを取得する方法

Posted at

前回、Next.jsを使ったクライアントサイドでのクエリパラメータを取得する方法を解説しました。

Next.jsでクエリパラメータを遷移先に渡すにはどうすればいいのか? - Qiita

前回使用したuseRouterフックはクライアントサイドで動きますが、サーバーサイドではエラーになります。そのためサーバーサイドでクエリパラメータを取得するには別の方法が必要です。

なので、今回はサーバーサイドでクエリパラメータを取得する方法を解説します。

サーバーサイドレンダリングでクエリパラメータを取得する方法

まずはサーバーサイドでレンダリングするためgetServerSidePropsの定義が必要です。その際の注意点としてはexportayncキーワードをつけることです。これにより、リクエスト毎にこのページを事前にレンダリングします。

そして、このgetServerSidePropsの中でuseRouterを使おうとするエラーが発生します。

WS000002.JPG

これはサーバーサイドレンダリングではuseRouterを使えないためです。クライアントサイドで使う前提になっています。

ここで使えるのがgetServerSidePropsの引数です。通常contextという名前で設定しますが、どんな引数名でも使えるはずです。

このcontextの中には

  • req:HTTPリクエストオブジェクト
  • res:HTTPレスポンスオブジェクト
  • query:クエリパラメータ

が入っています。この中のqueryの中にクエリパラメータの値が格納されているので、この値を使えばサーバーサイドレンダリングでも使うことができます。

たとえば、次のページを作る際には2つのページが必要になります。

Nextjsのパラメータ引き渡し(サーバーサイドレンダリング).gif

  1. クエリパラメータを送るページ
  2. クエリパラメータを受け取るページ

クエリパラメータを受け取るページでは、受け取った値でWebAPIを呼び出してGoogleブックの検索結果を表示しています。

クエリパラメータを送るページ

index.jsx
import { useRouter } from 'next/router';
import {useState} from 'react';

export default function Index() {
  const router = useRouter();                //ルーターの取得
  const [keyword, setKeyword] = useState();  //検索キーワード

  // ボタンをクリックしたときの処理
  const clickButton = () => {
    //未入力の時
    if (!keyword) {
      return;
    }

    router.push({
        pathname:"/result",       //URL
        query: {keyword :keyword} //検索クエリ
      });
  }

  return (
    <div style={{textAlign: "center", marginTop: "50px"}}>
      {/* 入力項目 */}
      <input 
        type="text" 
        value={keyword}
        onChange={(e) => setKeyword(e.target.value)} /*変更時keywordに値をセット*/
      />

      {/* ボタン */}
      <button 
        onClick={clickButton}
        disabled={!keyword}>    {/*入力項目が未入力の場合、非活性*/}
        検索
      </button>
    </div>
  )
}

クエリパラメータを送信するページではuseRouterフックを使って画面遷移とクエリパラメータの設定を行っています。router.pushメソッドの引数にURLとクエリパラメータをセットしています。

  • pathname:URL
  • query:クエリパラメータ

注意点としてはクエリパラメータは連想配列で設定します。複数セットする可能性があるためです。

クエリパラメータを受け取るページ

//サーバーサイドレンダリング
export async function getServerSideProps(context) {
  //検索キーワード
  const keyword = context.query.keyword;

  //Googleブックで検索
  const response = await fetch (encodeURI(`https://www.googleapis.com/books/v1/volumes?q=${keyword}`));

  return {
    props: {
      bookList: await response.json(),  //Googleブックの戻り値
      keyword: keyword,                 //検索キーワード
    }
  }
}

export default function Result(props) {

  //Googleブックの情報を取得
  const bookList = props.bookList.items.map(item => item.volumeInfo).map(((item) => {
    return {
      title : item.title,                             //タイトル
      url   : item.infoLink,                          //URL
    }
  }));

  return (
    <div style={{marginLeft: "50px", marginTop: "50px"}}>
      <h1>検索キーワード:{props.keyword}</h1>

      {/* 検索データの表示 */}
      <ul>
        {bookList.map((item) =>
          <li>
            <a href={item.url}>{item.title}</a>
          </li>
        )}
      </ul>
    </div>
  )
}

一方、遷移先ページではgetServerSidePropsメソッド内でクエリパラメータを取得してgoogleブックで検索した結果をリストで表示しています。

クエリパラメータはcontext.query.keywordで取得しています。keywordの部分は遷移元で設定した名前です。

後は、getServerSidePropsの戻り値のpropsにクライアントサイドに渡したい値をセットして表示するだけです。クライアント側でbookList変数で取得した検索結果を加工して、map関数を使ってリスト表示しています。

まとめ

  • router.pushpathnameに遷移先URL、queryにクエリパラメータをセットする
  • getServerSidePropsを使うことでサーバーサイドレンダリングを利用できる
  • 引数のcontext.query内に遷移元から送られたクエリパラメータが取得できる
26
18
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
26
18