462文字
2分
編集

Q. React-RouterでURLをリダイレクトさせたら元のページに戻れなくなった。

リダイレクトさせるときに replace させないと、リダイレクトされるページの前にいたページへ戻れなくなるのは当たり前だと思うが、質問があったのでまとめた。“元のページ”は”リダイレクトが発生するページ”なのか、“リダイレクトが発生するページの前にいたページ”なのかで認識に齟齬があり説明に難儀した。

リダイレクトする際に replace させないと元のページにブラウザのバックボタンから戻れなくなる。

たとえば /shop/list/shop/items/:itemid のような URL を考える。

/shopやそれ以下の存在しない URL にアクセスすると/listにリダイレクトされるような Routes を定義し、ItemPage からはいつでも list ページに戻れるようなボタンを設置した。ただしこのとき list ページの URL は変更される可能性があったため、あえてリダイレクトを前提としたnavigate("/shop")のような記述をした。

tsx
const ItemPage = () => {
  return (
    <Button
      onClick={() => {
        navigate("/shop");
      }}
    >
      Back to List
    </Button>
  );
};

const routes: RouteObject[] = [
  {
    path: "/list",
    element: <ListPage />,
  },
  {
    path: "/items/:itemId",
    element: <ItemPage />,
  },
  {
    path: "*",
    element: <Navigate to="list" />,
  },
];

この状況で、ItemPage から ListPage に戻ると、ブラウザのバックボタンで ListPage から離脱できなくなる。 これは history が以下のようになっているためである。

plaintext
 0: /shop/items/0
 1: /shop/items/1
 2: /shop
 3: /shop/list

この状況でブラウザバックをすると 2 の URL/shopにアクセスしようとするため、その度に/shop/listページへリダイレクトすることになる。

tsx
const routes: RouteObject[] = [
  { path: "*", element: <Navigate to="list" replace /> },
];

replace を付けておくことで、この状況は回避できる。replace を付けておけば history は以下のようになるため/shop/items/1へ戻ることができるようになる。

plaintext
 0: /shop/items/0
 1: /shop/items/1
 2: /shop/list
編集