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

React 18 Fallback not showing with useTransition after delay exceeds timeoutMs #22242

Closed
jacobp100 opened this issue Sep 3, 2021 · 4 comments
Labels
React 18 Bug reports, questions, and general feedback about React 18 Type: Discussion

Comments

@jacobp100
Copy link

I've tried the latest version of React 18 (as of today), and made a very simple test bed for the new APIs.

I've got the full gist here - but for brevity, I've only copied the important bits below

const SUSPENSE_CONFIG = { timeoutMs: 1000 };
const RESOURCE_DELAY = 2000;

// function Resource({ id }) { ... }

function App() {
  const [id, setId] = useState(undefined);
  const [isPending, startTransition] = useTransition(SUSPENSE_CONFIG);

  const incrId = useCallback(() => {
    setId((id) => (id != null ? id + 1 : 0));
  }, []);

  return (
    <>
      <h1>{id != null ? `Resource ${id}` : "Example"}</h1>
      <Suspense fallback={<div>Loading...</div>}>
        {id != null ? <Resource id={id} /> : <div>Nothing loaded</div>}
      </Suspense>
      <button type="button" onClick={incrId}>
        Load WITHOUT Transition
      </button>
      <button type="button" onClick={() => startTransition(incrId)}>
        Load WITH Transition {isPending ? "(Pending...)" : null}
      </button>
    </>
  );
}

From my understanding, if I click the Load WITH Transition button, I should see (Pending...) in the button for a second, then the Loading... should show for a second, then both loading states are cleared as the resource is loaded.

However, I cannot get the fallback to show when using useTransition. If I don't use that - the fallback loads perfectly.

Is this a bug, or am I misunderstanding how this works?

@jacobp100 jacobp100 added React 18 Bug reports, questions, and general feedback about React 18 Type: Discussion labels Sep 3, 2021
@gaearon
Copy link
Collaborator

gaearon commented Sep 6, 2021

Yeah, we removed timeoutMs: #19703.

Haven't had a chance to update the docs because the update would need to be quite extensive, and we plan to remove those docs in favor of some new documentation before a stable release anyway.

Hope this helps!

@gaearon gaearon closed this as completed Sep 6, 2021
@jacobp100
Copy link
Author

Thanks for taking the time to reply and find the relevant PR! Was really helpful to see the thoughts behind it too.

Is it still the case that you’re no longer immediately looking to solve the issue of loading spinners existing for a few milliseconds when loading new data?

I suppose you could implement a similar effect user-land with a hook that takes a function that loads a resource, catches the thrown promises, returns old data for timeoutMs, and then re-thrones the promises that timeout.

@gaearon
Copy link
Collaborator

gaearon commented Sep 6, 2021

Is it still the case that you’re no longer immediately looking to solve the issue of loading spinners existing for a few milliseconds when loading new data?

Yes. Broadly speaking, we could still introduce some heuristics deferring or throttling the spinners, but for now we’re not focusing on that problem. In the long term, we’d like to use animated transitions to avoid “flashes”, with Exit Animations allowing the fallback to leave gracefully instead of suddenly. reactjs/rfcs#154 (comment)

I suppose you could implement a similar effect user-land with a hook that takes a function that loads a resource, catches the thrown promises, returns old data for timeoutMs, and then re-thrones the promises that timeout.

I wouldn’t suggest something like this. It sounds pretty complicated and probably breaks expectations in subtle ways. There are very specific rules about what Suspense implementations should do, and throwing Promises is only a part of that. We haven’t documented them in detail yet, but the tldr is that you should think of Suspense implementations as always being backed by some sort of a cache. The Promises you throw must be the same ones for the same content (not always new ones), they must be cached, and they most consistently be thrown (not dependent on timing) until they resolve. After they resolve the same value must consistently be returned until the cache gets replaced. (The mechanisms for this aren’t covered by a stable API yet.) That is to say — I wouldn’t recommend building anything that tries to “orchestrate” throwing Promises based on timing.

@gavin-c-tcg
Copy link

gavin-c-tcg commented Sep 28, 2022

How do I know the time spent in isPending?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
React 18 Bug reports, questions, and general feedback about React 18 Type: Discussion
Projects
None yet
Development

No branches or pull requests

3 participants