DEV Community

Practical data fetching with React Suspense that you can use today

Andrei on April 17, 2020

It's the hottest topic these days in the React community, and everybody gets either super excited or completely confused when the word "Suspense" i...
Collapse
 
ruinerwarrior profile image
Rick Nijhuis

Nice article!, one question though, wouldn't it be simpler and maybe more performant if you just passed the promise instead of a method returning a promise? per example:

const promise = (() => { const resp = await fetch("http://url"); return resp.json })()
useAsyncResource(promise);

No need for caching the request because it's already executed and doesn't need to be executed inside the function.

Collapse
 
andreiduca profile image
Andrei

Calling fetch immediately will start the api call immediately. But data needs to be retrieved on demand, and usually with parameters (fetch a user by its id). You cannot create fetch promises for all possible IDs you don't know you're going to use.

Also, we're not caching the fetch requests (i.e. the functions that return the promises), but the generated data reader functions (i.e. the functions that just return the data, or throw the in-progress promises).

Collapse
 
zackdotcomputer profile image
Zack Sheppard

Thanks for writing this post up last year - I'm really enjoying playing around with the library!

I'm trying to wrap my head around Suspense and the thing I can't figure out right now, though, is why you have the pattern of calling your hook outside of the Suspense barrier and then passing the throwing reader function into the child component inside the barrier. This seems more difficult to reason about than the pattern in reactfire where the hook call itself can throw a promise. Is there something I'm missing here about Suspense or is this just a convention difference?

Collapse
 
zackdotcomputer profile image
Zack Sheppard

Ok, I think I figured it out.

The issue is that you need some way to persist the state that is in flight to some point outside of the Suspense boundary. Because the Suspense-aware API requires throwing a value, it interrupts the execution of the component(s) underneath the nearest Suspense component, meaning that any values in their state (including their hooks' states) are wiped out.

reactfire gets away with its design pattern because it has the context provider higher up in the component tree where it can hang the loads in progress.

Collapse
 
siddiqnx profile image
Siddiq Nx

Hi Andrei, nice article! I'm new to react and I just have some questions. You use this in production which means you are using the react concurrent mode, right?

Did you come across any compatibility or any other issues in production? Does your package use-async-resource need react concurrent mode? Can I use your use the package for my project safely?

Collapse
 
andreiduca profile image
Andrei

Hi Siddiq. As explained in the article, the use-async-resource package is working with current versions of React, without concurrent mode.

Collapse
 
allforabit profile image
allforabit

Out of interest do you still use redux observable and do you foresee use cases for it alongside suspense? I.e. for a new project do you think you'd end up bringing redux observable into the mix? Thanks for the article!

Collapse
 
andreiduca profile image
Andrei

In theory, you could hook up your redux (and redux observables) setup with Suspense. In practice, however, I think Suspense lets you move away from that.

Redux (and especially redux observables) requires a lot of under-the-hood boilerplate, and all data flows are created outside your JSX. With Suspense, you can control the flow of data directly from JSX, and handling loading and error states becomes so much simpler. And if you need to use and manage pieces of data in multiple places, a simple context provider can do the job.

Collapse
 
memark profile image
Magnus Markling • Edited

This is a fantastic post! Very well written!

(I just joined dev.to only to be able to follow you!)

You think you'll be maintaining the git repo and npm package going forward?

Collapse
 
andreiduca profile image
Andrei

Thank you! I'm glad you enjoyed the read. :D

Yes, I'll do my best to keep it up to date!

Collapse
 
mihaisavezi profile image
Mihai

Beautifully explained and detailed. Thank you.