Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: AbortSignal won't get aborted if defer returned from loader #10772

Closed
shura-v opened this issue Aug 9, 2023 · 4 comments
Closed

[Bug]: AbortSignal won't get aborted if defer returned from loader #10772

shura-v opened this issue Aug 9, 2023 · 4 comments
Labels

Comments

@shura-v
Copy link

shura-v commented Aug 9, 2023

What version of React Router are you using?

6.14.2

Steps to Reproduce

  1. Using little App component below, try clicking Index and Info links.
  2. Check the console.
import { Suspense } from "react";
import {
  RouterProvider,
  createBrowserRouter,
  Link,
  Outlet,
  defer,
  Await,
  useLoaderData,
} from "react-router-dom";

const router = createBrowserRouter([
  {
    element: (
      <>
        <ul>
          <li>
            <Link to="/">Index</Link>
          </li>
          <li>
            <Link to="/info">Info</Link>
          </li>
        </ul>
        <Outlet />
      </>
    ),
    children: [
      {
        index: true,
        element: <>Index</>
      },
      {
        path: "info",
        loader({ request }) {
          request.signal.addEventListener("abort", () => {
            console.log("signal aborted");
          });
        
          return defer({
            info: new Promise((resolve) => {
              setTimeout(() => resolve("eulav cnysA"), 5000);
            })
          });
        },
        Component() {
          const { info } = useLoaderData();

          return (
            <Suspense fallback={<>Loading...</>}>
              <Await resolve={info}>
                {data => data}
              </Await>
            </Suspense>
          );
        }
      }
    ]
  }
]);

export default function App() {
  return <RouterProvider router={router} />;
}

Expected Behavior

AbortSignal is aborted when I'm leaving Info page

Actual Behavior

Signal is not aborted

@shura-v shura-v added the bug label Aug 9, 2023
@brophdawg11
Copy link
Contributor

This is expected behavior when using defer. The abort signal on the request is for the navigation from one route to another. When you are using defer, you're telling React Router to complete the navigation without waiting for the data to resolve, and you'll let that data stream in later. So as soon as the loader returns - we successfully render /info and the navigation is considered completed and the abort controller is cleaned up.

Internally, we cancel our listeners on the pending defer promises so when they eventually resolve/reject they are ignored by React Router.

Can you elaborate a bit on your use case and maybe there's an alternate approach to do what you're trying to do?

@brophdawg11 brophdawg11 closed this as not planned Won't fix, can't repro, duplicate, stale Aug 10, 2023
@shura-v
Copy link
Author

shura-v commented Aug 10, 2023

I use the defer function for heavy requests to the server, for which you can render a fallback at a certain place on the page using Suspense and Await (as it is written in the docs). My logic was straightforward and I expected that if the user decided not to wait for heavy request to finish loading and go to another page, then the connection for that request drops, thereby reducing the load on both the client and the server.

@shura-v
Copy link
Author

shura-v commented Aug 11, 2023

Is there any way right now to use Suspense/Await and signals (coming from loader's request) at the same time?

@brophdawg11
Copy link
Contributor

Not at the moment, there is an internal AbortController for pending defer calls - but it's not currently exposed. If you'd like, you can write up a Proposal for this functionality and we can look into adding it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants