Skip to content

useNavigate.navigate() resolves before a blocker proceeds #14158

@Artur-

Description

@Artur-

Reproduction

When you have some code that needs to perform two navigation operations programmatically, you can have something like this

    const navigate = useNavigate();
...
await navigate("foo");
await navigate("foo?bar", {replace: true});

Which works fine, but if you add a blocker to the mix and have e.g.

    const navigate = useNavigate();
  const blocker = useBlocker(true);
  useEffect(() => {
    setTimeout(() => {
      if (blocker.state === 'blocked') {
        blocker.proceed();
      }
    }, 500);
  }, [blocker.state]);
...
await navigate("foo");
await navigate("foo?bar", {replace: true});

Then it no longer works correctly because the first await navigate("foo"); will not actually wait for navigation, it will only wait for the blocker to be blocked. The second navigate call will then invoke before the blocker has been able to proceed, and seemingly overwrite the first call. As a result, the history is incorrect.

Is there a reason that navigate does not await the blocker to proceed and only at that point resolve? Then this should work also when using a blocker

Example in https://stackblitz.com/edit/github-llreimye?file=app%2Froutes%2Fhome.tsx

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 20.19.1 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.8.2 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @react-router/dev: ^7.7.1 => 7.8.0 
    @react-router/node: ^7.7.1 => 7.8.0 
    @react-router/serve: ^7.7.1 => 7.8.0 
    react-router: ^7.7.1 => 7.8.0 
    vite: ^6.3.3 => 6.3.5

Used Package Manager

npm

Expected Behavior

useNavigate() should behave like it is documented:

The implementation in Data/Framework mode also returns a Promise that resolves when the navigation is completed.

Actual Behavior

The returned promise resolves before the navigation is completed

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions