この記事はNext.jsの個人学習のアウトプットです。
Udemyの講座【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript(CodeMafia)から引用・参照・コピーペーストしています。
1.Next.jsとは
- React開発のためのフレームワーク
- 高度なアプリケーションを作成するために、様々な機能を提供
┗ルーティングやサーバー側でのレンダリングなど - Vercelが提供している
Reactとの違い
-
React
UIを構築するための機能を提供するライブラリ -
Next.js
react開発のための機能を提供するフレームワーク
Next.jsの主な機能
- 複数のレンダリング方法(SSR、SG、ISG)
- ファイルベースルーティング(ダイナミックルート)
- APIの作成(API Routes)
- デベロッパーに優しい開発環境(ゼロコンフィグ)
2.ルーティング
Next.jsは、pagesフォルダ内のファイル(またはディレクトリ)構成に対応してルーティングを行います。
export default function Home() {
return (
<h1>Home</h1>
)
}
// http://localhost:3000/
ブラウザでlocalhost:3000にアクセスすると、作成したページが表示されます。
Next.jsはデフォルトエクスポートの関数がそのまま関数として表示されることになるので、例えば「blog-router」
というフォルダを作成し、index.js内で同じように関数コンポーネントをデフォルトエクスポートすると「blog-router」というパスに対してページが表示されます。
export default function Blog() {
return <h1>Blog Page</h1>
}
// http://localhost:3000/blog-router
index.js以外のファイルで作成した場合は、パスはjavascriptのファイル名まで続けて指定する必要があります。
export default function First() {
return <h1>Blog First Page</h1>
}
// http://localhost:3000/blog-router/first
実行結果
動的なルーティング
ダイナミックルーティングを用いると、URLの一部分を動的な値に変換することができるので、jsファイルのひとつだけ作成すればいいことになります。
123と数値が動的に変わっていくようなURLに対応するダイナミックルーティング
export default function Number() {
return <h1>[number] Page</h1>
}
// http://localhost:3000/blog-router/1
// http://localhost:3000/blog-router/2
// http://localhost:3000/blog-router/3
フォルダにダイナミックルーティングを用いることも可能です。フォルダ名に[name]にすると、動的に変更することが可能になります。
export default function Setting() {
return <h1>[name] Setting</h1>
}
// http://localhost:3000/blog-router/a/setting
// http://localhost:3000/blog-router/b/setting
// http://localhost:3000/blog-router/c/setting
3.指定されたパスの値をjsで取得する
動的に変化するパスをjsで取得するにはどうすれば良いでしょうか。
2つの方法があります。
方法①getServerSideProps
という関数を使用する
propsというプロパティに設定された値が、この関数コンポーネントのpropsとして渡ってきます。
// propsにhelloを渡す
export default function Setting({ hello }) {
return <h1>{hello}</h1>
}
export async function getServerSideProps(){
return {
props: { hello: "こんにちは" }
}
}
queryを用いて、動的なパス部分を取得
今回の[name]の動的なパスに関しては、引数でcontextが渡ってきて、その中のqueryというオブジェクトの中に格納されています。
queryを渡してあげれば、画面上をどのようなパスで渡ってきたのか表示することができます。
export default function Setting({ query }) {
return <h1>{query.name}</h1>
}
export async function getServerSideProps({ query }){
return {
props: { query }
}
}
方法② Next.jsが提供するRouterというライブラリからReactフックを読み込む
import { useRouter } from "next/router";
export default function Setting({ query }) {
const router = useRouter();
return <h1>routerから取得:{router.query.name}</h1>;
}
export async function getServerSideProps({ query }) {
return {
props: { query },
};
}
これら2つの方法で、動的なルートの部分を取得することができます。
4.useRouter を使って画面遷移を行う
buttonタグにclickイベントを定義し、routerのpushメソッドを使用します。この時スラッシュとすれば、rootのパスに一致することになるので、TOPページに戻ることになります。
import { useRouter } from "next/router";
export default function Setting({ query }) {
const router = useRouter();
const clickHandler = () => {
router.push('/')
}
return (
<>
<h1>routerから取得:{router.query.name}</h1>
<button onClick={clickHandler}>アクションによる画面遷移</button>
</>
);
}
export async function getServerSideProps({ query }) {
return {
props: { query },
};
}
第二引数に対して例えば/dummy-url
と置くと、表示されるページはTOPページだが、URLのパスはhttp://localhost:3000/dummy-url
このダミーURLになる。
import { useRouter } from "next/router";
export default function Setting({ query }) {
const router = useRouter();
const clickHandler = () => {
router.push('/','/dummy-url')
}
return (
<>
<h1>routerから取得:{router.query.name}</h1>
<button onClick={clickHandler}>アクションによる画面遷移</button>
</>
);
}
// http://localhost:3000/dummy-url
export async function getServerSideProps({ query }) {
return {
props: { query },
};
}
5.Linkを使って画面遷移を行う
Reactの画面でリンクを置いて画面遷移を行う場合はリンクコンポーネントを使用します。
import Link from "next/link"
export default function Home() {
return (
<>
<h1>Home</h1>
<Link href="/blog-router">
<a>blog-router</a>
</Link>
</>
);
}
// http://localhost:3000/
補足
<a href="/blog-router">blog-router</a>
これだと画面が更新され、リロードが走る。
Linkタグで囲むと、画面遷移が発生しない。
routerと一緒でas
を利用して仮想のURLを画面上で表示することも可能です。
例えばas="/dummy-url"
とすると、画面上では/dummy-url
に飛ぶが、リンクを押して遷移する先はこれまで通りblog-router
になる。
import Link from "next/link"
export default function Home() {
return (
<>
<h1>Home</h1>
<Link href="/blog-router" as="/blog-dummy">
<a>blog-router</a>
</Link>
</>
);
}
// http://localhost:3000/
hrefはオブジェクト形式で書くことも可能です。オブジェクトで書く場合にはpathnameのところに遷移させたいURLを記載し、queryも指定することで、URLの末尾にクエリパラメーターをつけることができます。
import Link from "next/link"
export default function Home() {
return (
<>
<h1>Home</h1>
<Link href={{ pathname: "/blog-router", query: { key: "value" } }}>
<a>blog-router</a>
</Link>
</>
);
}
// http://localhost:3000/
6.ページをまたぐ状態の保持の方法
下記のコードを実行します。
ボタンがクリックされると、routerのpushメソッドが呼ばれて画面遷移が発生します。その時のパスはgoToStep関数の第二引数で設定した/personal
で表示されますが、実体としては/multipage?step=${step}
このパスになります。
import { useRouter } from "next/router";
export default function Multipage() {
const router = useRouter();
// URLで渡されたパラメーターを取得
// stepがついてこなかった場合(nullまたはundefind)は初期値を0にする
const step = router.query.step ?? 0;
// 渡ってきたステップの値をパラメーターのステップの値として設定
const goToStep = (_step, asPath) => {
router.push(`/multipage?step=${_step}`, asPath);
};
return (
<div>
{step == 0 && (
<>
<h3>Step:{step}</h3>
{/* ボタンがクリックされたときに次のステップに遷移する */}
<button onClick={() => goToStep(1, "/personal")}>Next Step</button>
</>
)}
{step == 1 && (
<>
<h3>Step:{step}</h3>
<button onClick={() => goToStep(2, "/comfirm")}>Next Step</button>
</>
)}
{step == 2 && (
<>
<h3>Step:{step}</h3>
{/* 最後のボタンを押した時はstep==0のページの戻る */}
<button onClick={() => goToStep(0, "/multipage")}>Next Step</button>
</>
)}
</div>
);
}
実行結果
step:0 http://localhost:3000/multipage
step:1 http://localhost:3000/personal
step:2 http://localhost:3000/comfirm
ボタンをクリックすると遷移できるようになりましたが、上記はあくまでダミーのパスであり、単体でアクセスすることはできません。
このような時に、このパスを直接指定された時に動かすために、リライト
という仕組みを用いることがあります。
next.config.jsにrewrites
という設定を追加します。
今回の場合では、/personal
というパスにリクエストが来た時にdestination
に記載されたパスのコンポーネントを動かすことができます。
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
async rewrites() {
return [
{
source: "/personal",
destination: "/multipage?step=1"
},
{
source: "/comfirm",
destination: "/multipage?step=2"
}
]
}
}
module.exports = nextConfig
サーバを一度再起動すると、直接アクセスすることが可能になりました。
まとめ
プロジェクト構成
- /pages
ファイルまでのパスがそのままページになる - styles
グローバルに適用されるスタイルを配置 - /pages/_app.js
ページ遷移時に必ず呼ばれる処理を記述 - next.config.js
Next.jsの設定を記載
ルーティング
- pages配下からexportされたコンポーネントを1ページとしてルーティングする
- [id]は動的なパスとして認識される
- getServerSideProps
queryでダイナミックルートを取得する
ページ遷移
-
useRouter
ページ遷移を行うための値やメソッドを取得する際に利用 -
Link href
hrefに遷移先のURLを設定する
参考
【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript(CodeMafia)