Handling
Async
State
with
React
Query
What is React Query?
Data-fetching library for React.
Makes fetching, caching, synchronizing and updating server state in a React application a breeze.
How can I know if I need React Query?
You might be handling async state wrong
This is because server state is totally different.
- Is persisted remotely in a location you do not control or own
- Requires asynchronous APIs for fetching and updating
- Implies shared ownership and can be changed by other people without your knowledge
- Can potentially become "out of date" in your applications if you're not careful
Caching
Deduping multiple requests
Updating stale data in the background
Knowing when data is "out of date"
Reflecting UI updates faster
+ Performance optimizations (lazy, pages...)
Server state memory and garbage collector
Memoizing query results
Less code to handle fetch and refetch
More maintainable code
Potentially helps saving bandwidth
Direct impact on end-users
Potentially decrease BE load
TypeScript
...
Scroll Restoration
Even more stuff!
React Query Devtools
What matter is all the possibilites and challenges we can now face.
This does not replace Redux or any form of handling client state
How does React Query does its magic?
React component
React component
React component
React component
projects
React component
React component
React component
React component
projects
query
query
query
query
read
create
update
delete
React component
React component
React component
React component
query
query
query
query
read
create
update
delete
projects
React component
React component
React component
React component
projects
query
query
query
query
read
create
update
delete
queryCache
what about under the hood?
// whenever we call useQuery('myQueryName', service.getData)
// React-Query does this under the hood
// (simplified)
getResolvedQueryConfig(config); // gets the query from the queryCache.
new QueryObserver() // new instance of their own Observer implementation.
// Subscribe to the observer
React.useEffect(() => {
errorResetBoundary.clearReset()
return observer.subscribe(() => {
if (isMounted()) {
rerender()
}
})
}, [isMounted, observer, rerender, errorResetBoundary])
// more stuff, like handling Suspense
const result = observer.getCurrentResult()
// Gives us an instance of QueryResult, a prop in the QueryObserver class
// which has the callbacks in case another query has been modified
// or set to "stale" to fetch the data again, and more stuff.
return result;