Skip to content

[Bug] Routes: redirect does pushState instead of replaceState, breaking browser back buttons #8703

Closed
@tonywu6

Description

@tonywu6

What happens?

redirect routes now update window locations by doing a window.history.pushState instead of window.history.replaceState. This renders browsers' back buttons useless as trying to go to the previous page lands us in the location with redirect, bouncing us back to the most recent page.

Minimal Reproducible Example

https://github.com/tonywu6/umi-4-issue-redirect

How To Reproduce

  1. Create a minimal umi app; in app config, in routes, provide the following
  routes: [
    { path: '/', component: 'index' },
    {
      path: '/lorem',
      routes: [
        {
          path: '',
          redirect: 'ipsum',
        },
        {
          path: 'ipsum',
          routes: [
            {
              path: '',
              redirect: 'dolor',
            },
            {
              path: 'dolor',
              component: 'main',
            },
          ],
        },
      ],
    },
  ],
  1. Start the dev server, then navigate to /;
  2. Navigate to /lorem;
  3. Observe that the page is redirected to /lorem/ipsum/dolor;
  4. Try returning to / using the back button;
  5. Observe that it is impossible to return to /; observe that the address briefly changes to /lorem/ipsum, then changes back to /lorem/ipsum/dolor.
Screen.Recording.2022-07-25.at.8.33.41.PM.mov

Expected behavior

After landing on a page via redirects, I should still be able to visit whatever previous page was using the back button.

Current behavior

It is impossible to return to the previous page using the back button.

Context

  • Umi Version: 4.0.8
  • Node Version: v14.18.1
  • Platform: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36

Previously, with react-router@5, redirecting is done by the <Redirect> component. With that gone in react-router@6, redirecting is instead done by <Navigate>:

element: redirect ? (
<NavigateWithParams to={redirect} />
) : (

where <NavigateWithParams> is

function NavigateWithParams(props: { to: string }) {
const params = useParams();
const propsWithParams = {
...props,
to: generatePath(props.to, params),
};
return <Navigate {...propsWithParams} />;
}

The replace prop is needed in <Navigate> for it to use replaceState.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions