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

plugin: React-Query for Data Fetching #6

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

codinsonn
Copy link
Contributor

@codinsonn codinsonn commented Apr 18, 2024

Plugin features when merged

  • Install and set up @tanstack/react-query for use on Browser, Mobile and Serverside
  • Use @tanstack/react-query to create a UniversalRouteScreen wrapper for data fetching everywhere

Recommended workflow

Graph showing the Unversal Route Screen component using a fetcher with React-Query to retrieve the props for a RouteComponent before rendering on Web, iOS and Android

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

@codinsonn codinsonn self-assigned this Apr 18, 2024
Copy link

vercel bot commented Apr 18, 2024

The latest updates on your projects. Learn more about Vercel for Git β†—οΈŽ

Name Status Preview Comments Updated (UTC)
universal-app-router βœ… Ready (Inspect) Visit Preview πŸ’¬ Add feedback Jul 24, 2024 2:18pm
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
universal-base-starter-docs ⬜️ Ignored (Inspect) Visit Preview Jul 24, 2024 2:18pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant