React-Query for Data Fetching
git merge with/react-query
Plugin features when merged
- Install and set up
@tanstack/react-query
for use on Browser, Mobile and Serverside - Use
@tanstack/react-query
to create aUniversalRouteScreen
wrapper for data fetching everywhere
Recommended workflow
1. Start with component & bridge in /screens/
folder
SomeScreen.tsx
import { someFetcher } from '../resolvers/some.fetcher'
import { createQueryBridge, HydratedRouteProps } from '../navigation/UniversalRouteScreen.helpers'
/* --- Data Fetching ----------- */
// -i- Think of a "bridge" as a universal version of `getServerSideProps()` from next.js
// -i- ...which will work on Expo / Mobile / iOS / Android as well as on server / browser
const queryBridge = createQueryBridge({
// Transform the route params into things useable by react-query
routeParamsToQueryKey: (routeParams) => ['subpage', routeParams.slug],
routeParamsToQueryInput: (routeParams) => ({ slug: routeParams.slug }),
// Provide the fetcher function to be used by react-query
routeDataFetcher: someFetcher,
// Transform fetcher output to props after react-query was called
fetcherDataToProps: (fetcherData) => ({ someProp: fetcherData }),
})
/* --- <SomeScreen/> ----------- */
// Component for screen UI can infer types from "bridge" 👇
const SomeScreen = (props: HydratedRouteProps<typeof queryBridge>) => {
// Props with inferred types 🙌
const { someProp } = props
// Render screen UI
// ...
}
2. Use bridge & component in workspace /routes/
folder
/routes/subpages/[slug]/index.ts
— in e.g. the @app/core
workspace
import { SomeScreen, queryBridge } from '@app/screens/SomeScreen'
import { UniversalRouteScreen } from '@app/navigation'
/* --- /subpages/[slug] ----------- */
export default (props) => (
<UniversalRouteScreen
{...props}
// Will execute each step from the bridge in sequence to get to the final props
queryBridge={queryBridge}
// Will provide the final props to the screen component on iOS, Android, server & browser
routeScreen={SomeScreen}
/>
)
💡 The reason we define the route in a workspace is so we can re-use this file in both Expo & Next.js 👇
3. Reexport route file in Expo & Next.js app routers
app/subpages/[slug]/index.ts
in @app/expo
workspace
import SlugRoute from '@app/routes/subpages/[slug]'
export default SlugRoute
app/subpages/[slug]/page.ts
in @app/next
workspace
import SlugRoute from '@app/routes/subpages/[slug]'
export default SlugRoute
// -i- Export any other next.js routing config here
// -i- See: https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config
export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
export const maxDuration = 5
✨ If you’d like this last step to happen automatically, we have a script to do this in the FullProduct.dev ⚡️ Starterkit demo #9 plugin: GREEN-stack.
💡 Improving it with GraphQL
This is fully optional, but pairing this pattern with something like GraphQL (e.g. #5 plugin: Apollo GraphQL) is actually a great combo, because:
- ✅ You can create executable GraphQL schemas
- ✅ Meaning you can execute the same query during SSR, CSR (Web) and on Mobile (iOS & Android)
This is one of the reasons I recommend GraphQL for fetching data in Universal apps. We recommend you create or use some universal GraphQL fetcher together with graphql.tada 🪄
🚀 We’ve perfected this Universal Data Fetching pattern in the FullProduct.dev ⚡️ Starterkit.
Demo 👉 #9 plugin: GREEN-stack
Official @tanstack/react-query
docs
https://tanstack.com/query/latest/docs/framework/react/overview
Disclaimer
with/react-query
branch is a git based plugin to help test the free version of the ‘FullProduct.dev’ Universal App Starterkit. You can look at the PR #6 - React-Query for Data Fetching to inspect the diff and learn what code changes together to enable this feature… OR you can check it out locally to test / edit in isolation until ready to merge.