0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

遷移したページに情報を渡したい!

0
Last updated at Posted at 2026-02-28

ページ遷移時に遷移先のページに何らかの情報を渡したい場面があるかと思います。

例えば商品一覧から商品詳細画面に移動するときは、商品のidを渡したいかもしれません。検索フォームに入力した値を、検索結果表示画面でも使いたくなるかもしれません。

このような時にreact-router-domが1つの選択肢としていいなと思ったので、アウトプットがてら紹介します。

ケース

例として、以下のようなケースを考えます。

  • 計算画面(Cal.tsx)では、フォームに入力された値をもとに計算を行います
  • ユーザーは、計算された値を確認し、この値を使って登録画面(Registration.tsx)から、データの登録を行うことができます
Cal.tsx
import { useState } from "react"
import { useNavigate } from "react-router-dom"

export default function Cal() {
  const navigate = useNavigate()

  const [unitPrice, setUnitPrice] = useState("")
  const [quantity, setQuantity] = useState("1")

  const u = Number(unitPrice)
  const q = Number(quantity)

  const subtotal = Number.isFinite(u) && Number.isFinite(q) ? u * q : NaN

  const onClick = () => {
    // 遷移先のページにsubtotalを渡したい!
    navigate("/registration")
  }

  return (
    <div>
      <h1>計算</h1>

      <input value={unitPrice} onChange={(e) => setUnitPrice(e.target.value)} placeholder="単価" />
      <input value={quantity} onChange={(e) => setQuantity(e.target.value)} placeholder="数量" />

      <p>合計: {Number.isFinite(subtotal) ? subtotal : "-"}</p>

      <button onClick={onClick} disabled={!Number.isFinite(subtotal)}>
        登録へ
      </button>
    </div>
  )
}
Registration.tsx
export default function Registration() {
  // subtotalはCal.tsxで計算した値を入れたい!
  const subtotal = 0

  return (
    <div>
      <h1>登録</h1>
      <p>受け取った subtotal: {subtotal}</p>

      {/* ここで subtotal を使って登録処理(API呼び出し等) */}
      <button onClick={() => alert(`登録しました(subtotal=${subtotal})`)}>
        登録する
      </button>
    </div>
  )
}

方法1:URLに含める

やり方の1つはパスパラメータやクエリパラメータとして渡すという方法です。

Cal.tsx
const onClick = () => {
  navigate(`/registration?subtotal=${subtotal.toString()}`)
}
Registration.tsx
export default function Registration() {
	const [searchParams] = useSearchParams()
	const raw = searchParams.get("subtotal") // string | null
	const subtotal = raw ? Number(raw) : NaN

このようにすれば値を渡すことができます。
ただ、渡したい値が増えると可読性などの問題がありますし、URLに含めるにはセキュリティ等の観点から難しい値(例:機微情報など)はこの方法を使うことができません。

方法2:グローバルな状態を使う

useContextやReduxなど、どこからでもアクセスできる状態(state)に一度格納し、Registration.tsxでこれを取得する方法です。

(実装は面倒なので省略)

渡したい値が増えても対応できますが、正直実装が面倒です。グローバルな状態はどのコンポーネントからもアクセスできてしまうので、この点でもあまり好ましくない結果になることもあります。

方法3:useLocation()を使う

本題です。
react-router-dom には useLocation() が用意されており、これを使うことで、もっと簡単に遷移先のページに値を渡すことができます。

リロードすると値はリセットされる等のデメリットはありますが、一時的に、簡単な実装で渡すことができます!

Cal.tsx
import { useState } from "react"
import { useNavigate } from "react-router-dom"

export default function Cal() {
  const navigate = useNavigate()

  const [unitPrice, setUnitPrice] = useState("")
  const [quantity, setQuantity] = useState("1")

  const u = Number(unitPrice)
  const q = Number(quantity)

  const subtotal = Number.isFinite(u) && Number.isFinite(q) ? u * q : NaN

  const onClick = () => {
    if (!Number.isFinite(subtotal)) return
    
    // useLocationで取得できるように、値をセットする!
    navigate("/registration", { state: { subtotal } })
  }

  return (
    <div>
      <h1>計算</h1>

      <input value={unitPrice} onChange={(e) => setUnitPrice(e.target.value)} placeholder="単価" />
      <input value={quantity} onChange={(e) => setQuantity(e.target.value)} placeholder="数量" />

      <p>合計: {Number.isFinite(subtotal) ? subtotal : "-"}</p>

      <button onClick={onClick} disabled={!Number.isFinite(subtotal)}>
        登録へ
      </button>
    </div>
  )
}
Registration.tsx
import { useLocation } from "react-router-dom"

export default function Registration() {
	// useLocationを使ってsubtotalを取得!
  const location = useLocation()
  const subtotal = (location.state as { subtotal?: number } | null)?.subtotal

  if (typeof subtotal !== "number") {
    return <p>計算結果がありません。Cal画面から遷移してください。</p>
  }

  return (
    <div>
      <h1>登録</h1>
      <p>受け取った subtotal: {subtotal}</p>

      {/* ここで subtotal を使って登録処理(API呼び出し等) */}
      <button onClick={() => alert(`登録しました(subtotal=${subtotal})`)}>
        登録する
      </button>
    </div>
  )
}

まとめ

方式 メリット デメリット 利用に適したシーン
URLに含める(クエリ/パス) リロードしても保持される/URL共有で同じ状態を再現できる/デバッグしやすい(値が見える)/SSRや外部リンクと相性が良い ユーザーが改ざんできる(信用不可)/機微情報を載せられない/複雑なオブジェクトを扱いにくい(シリアライズ・長さ制限) 検索条件・フィルタ・ページング・ソート・タブ選択など「画面状態をURLで再現したい」ケース/サポート用にURL共有したいケース
グローバルstate(Redux/Zustand等) どこからでも参照可能/大きいデータ・複雑なオブジェクトを渡しやすい/多画面にまたがる状態管理が得意 リロードで消える(永続化しない限り)/依存が増えて追跡しづらい(どこでセットされたか見えにくい)/導入・設計コストが上がる(永続化するとさらに) ログインユーザー・権限・UI設定・カートなど「アプリ全体で使う状態」/ステップフォーム・ウィザードなど「複数画面で編集しながら最後に送る」
useLocation(location state)navigate(...,{ state }) URLが汚れない/実装が軽い(Redux不要)/オブジェクトをそのまま渡せる リロードで消える/直アクセス・URL共有で再現できない(遷移元前提)/戻る, 進むで想定外になり得る 「直前の遷移でだけ必要」な一時データ(確認画面へ渡す、編集画面の初期値、画面遷移理由のフラグなど)/URLに載せるほどでもなくグローバルに持つほどでもない値
0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?