O hirunewani blog

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

Created at

React-Routerでリダイレクトさせる際にreplaceさせないと、リダイレクトされるページの前にいたページに戻れなくなるのは当たり前だと思うが、質問があったのでまとめた。

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

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

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

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

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が以下のようになっているためである。

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

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

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

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

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