oedotme / generouted

Generated file-based routes for Vite
https://stackblitz.com/github.com/oedotme/generouted/tree/main/explorer
MIT License
1.02k stars 47 forks source link

Pending is not working on routes #166

Closed eleviven closed 2 months ago

eleviven commented 4 months ago

Describe the Bug

I tried adding and displaying a Pending element on the screen during data fetching on the Loader, but I got a white blank page instead. Is it possible to implement this feature using Pending?

Codes below.

export const Loader = async () => {
  const data = await new Promise((r) => {
    setTimeout(() => {
      r(true);
    }, 2000);
  });

  return data;
};

export const Pending = () => {
  return <div>Pending</div>;
};

export const Catch = () => {
  return <div>Error</div>;
};

const UsersPage: React.FC = () => {
  return (
    <div>
      <h1>Users Page</h1>

      <Link to="/">Go to Home Page</Link>
    </div>
  );
};

export default UsersPage;

Generouted Version

1.19.3

Your Example Website or App or Reproduction

https://stackblitz.com/edit/vitejs-vite-vuuhmq?file=src%2Fpages%2Fusers.tsx

Steps to Reproduce the Bug or Issue

  1. Go to Page
  2. Can't see pending

Expected Behavior

I expected to see the Pending element, but I can't see it. I see a blank page.

Screenshots or Videos

No response

Platform

Additional context

No response

oedotme commented 4 months ago

Hey @eleviven, that's seems to be the current behavior of React Router.

If you try to do the same with React Router APIs directly, you'll get the same result:

import { Suspense } from 'react'
import { createRoot } from 'react-dom/client'
import { Link, RouterProvider, createBrowserRouter } from 'react-router-dom'

const router = createBrowserRouter([
  {
    path: '/users',
    Component: () => (
      <Suspense fallback={<div>Pending</div>}>
        <div>
          <h1>Users Page</h1>
          <Link to="/">Go to Home Page</Link>
        </div>
      </Suspense>
    ),
    loader: async () => {
      const data = await new Promise((r) => {
        setTimeout(() => {
          r(true)
        }, 2000)
      })

      return data
    },
    ErrorBoundary: () => <div>Error</div>,
  },
])

const container = document.getElementById('app')!
createRoot(container).render(<RouterProvider router={router} />)

I'm pretty sure that used to work before, but I'm not aware since when it changed.

I've also tested the Pending component, and it works as expected. generouted wraps the page component with a Suspense component using the Pending component as a fallback:

import { Link } from '@/router'
import { lazy } from 'react'

const sleep = (duration: number) => new Promise((resolve) => setTimeout(resolve, duration))

const About = lazy(() =>
  import('./about').then(async (module) => {
    await sleep(2000)
    return { default: module.default }
  }),
)

export const Pending = () => {
  return <div>Pending...</div>
}

export const Catch = () => {
  return <div>Error</div>
}

const UsersPage: React.FC = () => {
  return (
    <div>
      <h1>Users Page</h1>
      <Link to="/">Go to Home Page</Link>

      <br />
      <br />
      <br />

      <div>Lazy loaded `About` page component</div>
      <About />
    </div>
  )
}

export default UsersPage

An open discussion/issue could be found at remix-run/react-router, otherwise please feel free to open a new issue there.

Hope that helps, thanks!