Why will Suspense for data fetching require a cache?
See original GitHub issueI’m integrating Suspense with React Async, and I’ve been reading up on how it’s supposed to work. All the resources I found talk about needing react-cache
or another cache mechanism for Suspense to work properly. However, none of the resources explain WHY Suspense needs a cache. Could someone explain that? I’ve been able to make it work without a cache. Am I missing something?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:12 (4 by maintainers)
Top Results From Across the Web
Suspense for Data Fetching (Experimental) - React
It's a mechanism for data fetching libraries to communicate to React that the data a component is reading is not ready yet. React...
Read more >Blog - A Complete Guide to Data Fetching with React Suspense
Suspense refers to React's new ability to “suspend” rendering while components are waiting for something and display a loading indicator.
Read more >Practical data fetching with React ... - DEV Community
Now our resource is cached, so if we request it multiple times, we'll get the same data reader function. If we want to...
Read more >Using Suspense and React Query: Tutorial with examples
Suspense simplifies managing loading states in React components, supporting fallbacks in case the component hasn't finished loading yet. These ...
Read more >What the heck is this in React ? (Suspense) - ITNEXT
Data fetching with Suspense and react-cache · return the data from cache, · if the cache doesn't contain the data, it will throw...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Sorry I didn’t see this issue earlier! This has nothing to do with optimisations.
Suspense requires a cache because when a tree suspends, we want to be able to throw that render attempt away. The just-created components’ state or refs are preserved. (Details may vary based on the situation, but at least it’s not preserved for the components that suspended.) If you keep data inside state or refs, it would have to be above the place that may suspend while mounting. Because if that data/Promise gets thrown away, then you’re going to have an infinite loop of render attempts, each time throwing a different Promise.
In that sense, yes, keeping it in a ref is a form of a “cache”. But this ref would have to be higher than any usage of that data, which presumably is close to the root. So you can’t just put it inside your Hook that suspends. That’s a rather unintuitive but an important limitation.
Another way to look at it is that data has a lifetime associated with it. But rendering has no lifetime. It’s just a render attempt. You need to attach data to something that lives on permanently. That “something” is a cache. It could be local state of a component sufficiently high up the tree. Or it could be an object outside of the component tree. In both cases you then need to decide how and when to invalidate the cache. And how to do this without breaking encapsulation between deep children and the cache owner.
Our current thinking is that this concept of a cache and how it invalidates is tied to the idea of navigation. That broadly speaking, we can navigate “forward” and “back”, and the intent matters. When we navigate forward, we don’t want to show potentially stale cached data from the cache. Instead, we want to refetch. (To enable faster transitions, however, we’ll want to embed data needed by top-level views of the next screen into responses for the previous screen.) When we go back, we want to show data from the cache. Unless there was a mutation, in which case we do refetch the data when it happens.
I know this is rather hand wavy at this point but just wanted to explain where we’re going and how we’re thinking about these problems.
If your suspended component unmounts as a result of a <Placeholder /> higher up in the tree you will lose your local state and refs. That’s why you need the data in something that lives outside your components: the cache.