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

AbortController is not properly caught in parent loader #3928

Open
brmzkw opened this issue Apr 3, 2025 · 0 comments
Open

AbortController is not properly caught in parent loader #3928

brmzkw opened this issue Apr 3, 2025 · 0 comments

Comments

@brmzkw
Copy link

brmzkw commented Apr 3, 2025

Which project does this relate to?

Router

Describe the bug

First of all, I'm sorry if the title of the issue does not describe what is happening.

I have two routes:

  • the __root route with a loader performing a call to fetch to a slow API
  • an index route with a loader also performing a call to fetch to a slow API

Both calls forward the abortController.signal to fetch to ensure the request is canceled if necessary.

The index route is displaying a text input, and whenever the user types something, navigate is used which triggers a route reload.

If too many reloads are run, the error message "signal is aborted without reason" is triggered from the root view.

Your Example Website or App

https://stackblitz.com/edit/tanstack-router-juizcyv2?file=src%2Froutes%2Findex.tsx

Steps to Reproduce the Bug or Issue

  1. write one character at a time in the text input: it works well
  2. write many characters simultaneously: an error is triggered

Expected behavior

The abort error should be caught.

Screenshots or Videos

Screen.Recording.2025-04-03.at.13.41.43.mov

Platform

Additional context

root.tsx:

import * as React from 'react';
import { Link, Outlet, createRootRoute } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';

export const Route = createRootRoute({
  component: RootComponent,

  loader: async ({ abortController }) => {
    try {
      const data = await fetch('https://httpstat.us/200?sleep=1000', {
        signal: abortController.signal,
      });
    } catch (e) {
      console.log('in __root, aborted');
      throw e;
    }
  },
});

function RootComponent() {
  return (
    <>
      <div className="p-2 flex gap-2 text-lg">
        <Link
          to="/"
          activeProps={{
            className: 'font-bold',
          }}
          activeOptions={{ exact: true }}
        >
          Home
        </Link>{' '}
        <Link
          to="/about"
          activeProps={{
            className: 'font-bold',
          }}
        >
          About
        </Link>
      </div>
      <hr />
      <Outlet />
      <TanStackRouterDevtools position="bottom-right" />
    </>
  );
}

index.tsx:

import * as React from 'react';
import { createFileRoute } from '@tanstack/react-router';

type Search = {
  filter: string;
};

export const Route = createFileRoute('/')({
  component: HomeComponent,

  validateSearch: (search: Record<string, unknown>): Search => {
    return {
      filter: (search.filter as string) || '',
    };
  },

  loaderDeps: ({ search }) => {
    return {
      filter: search.filter,
    };
  },

  loader: async ({ deps, abortController }) => {
    console.log('loading', deps.filter);
    try {
      const data = await fetch('https://httpstat.us/200?sleep=1000', {
        signal: abortController.signal,
      });
    } catch (e) {
      console.log('in index, signal aborted for', deps.filter);
      throw e;
    }

    console.log('loaded:', deps.filter);
    return { status: 'loaded: ' + deps.filter };
  },
});

function HomeComponent() {
  const search = Route.useSearch();
  const navigate = Route.useNavigate();
  const data = Route.useLoaderData();

  return (
    <div className="p-2">
      <h3>Welcome Home!</h3>

      <h4>Status: {data.status}</h4>

      <input
        className="bg-gray-300 border border-black"
        value={search.filter}
        onChange={(e) => {
          navigate({
            to: '/',
            search: {
              filter: e.target.value,
            },
          });
        }}
      />
    </div>
  );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant