File tree Expand file tree Collapse file tree 16 files changed +177
-73
lines changed Expand file tree Collapse file tree 16 files changed +177
-73
lines changed Original file line number Diff line number Diff line change 11import { Stack } from 'expo-router'
22import UniversalAppProviders from '@app/core/screens/UniversalAppProviders'
33import UniversalRootLayout from '@app/core/screens/UniversalRootLayout'
4+ import { Link as ExpoContextLink } from '@app/core/navigation/Link.core.native'
5+ import { useRouter as useExpoContextRouter } from '@app/core/navigation/useRouter.core.native'
6+ import { useRouteParams as useExpoRouteParams } from '@app/core/navigation/useRouteParams.core.native'
47
58// -i- Expo Router's layout setup is much simpler than Next.js's layout setup
69// -i- Since Expo doesn't require a custom document setup or server component root layout
710// -i- Use this file to apply your Expo specific layout setup:
811// -i- like rendering our Universal Layout and App Providers
912
13+ /* --- <ExpoRootLayout/> ----------------------------------------------------------------------- */
14+
1015export default function ExpoRootLayout ( ) {
16+ // Navigation
17+ const expoContextRouter = useExpoContextRouter ( )
18+
19+ // -- Render --
20+
1121 return (
12- < UniversalAppProviders >
22+ < UniversalAppProviders
23+ contextLink = { ExpoContextLink }
24+ contextRouter = { expoContextRouter }
25+ useContextRouteParams = { useExpoRouteParams }
26+ >
1327 < UniversalRootLayout >
1428 < Stack
1529 screenOptions = { {
Original file line number Diff line number Diff line change 11'use client'
22import React from 'react'
33import UniversalAppProviders from '@app/core/screens/UniversalAppProviders'
4+ import { Link as NextContextLink } from '@app/core/navigation/Link.core.web'
5+ import { useRouter as useNextContextRouter } from '@app/core/navigation/useRouter.core.web'
6+ import { useRouteParams as useNextRouteParams } from '@app/core/navigation/useRouteParams.core.web'
47
58// -i- This is a regular react client component
69// -i- It's still rendered on the server during SSR, but it also hydrates on the client
@@ -15,11 +18,22 @@ type NextClientRootLayoutProps = {
1518
1619/* --- <NextClientRootLayout/> ---------------------------------------------------------------- */
1720
18- const NextClientRootLayout = ( { children } : NextClientRootLayoutProps ) => (
19- < UniversalAppProviders >
20- { children }
21- </ UniversalAppProviders >
22- )
21+ const NextClientRootLayout = ( { children } : NextClientRootLayoutProps ) => {
22+ // Navigation
23+ const nextContextRouter = useNextContextRouter ( )
24+
25+ // -- Render --
26+
27+ return (
28+ < UniversalAppProviders
29+ contextLink = { NextContextLink }
30+ contextRouter = { nextContextRouter }
31+ useContextRouteParams = { useNextRouteParams }
32+ >
33+ { children }
34+ </ UniversalAppProviders >
35+ )
36+ }
2337
2438/* --- Exports --------------------------------------------------------------------------------- */
2539
Original file line number Diff line number Diff line change 1+ import React from 'react'
2+ import { UniversalLinkProps } from '../navigation/Link.types'
3+ import { UniversalRouterMethods } from '../navigation/useRouter.types'
4+ import { UniversalRouteScreenProps } from '../navigation/useRouteParams.types'
5+ import type { useLocalSearchParams } from 'expo-router'
6+
7+ // -i- This context's only aim is to provide React Portability & Framework Ejection patterns if required
8+ // -i- By allowing you to provide your own custom Link and Router overrides, you could e.g.:
9+ // -i- 1) Support Expo for Web by not defaulting to Next.js's Link and Router on web
10+ // -i- 2) Eject from Next.js entirely and e.g. use another framework's Link component and Router
11+
12+ /* --- Types ----------------------------------------------------------------------------------- */
13+
14+ export type CoreContextType = {
15+ contextLink : ( props : UniversalLinkProps ) => JSX . Element
16+ contextRouter : UniversalRouterMethods
17+ useContextRouteParams : ( routeScreenProps : UniversalRouteScreenProps ) => ReturnType < typeof useLocalSearchParams >
18+ }
19+
20+ /* --- Context --------------------------------------------------------------------------------- */
21+
22+ export const CoreContext = React . createContext < CoreContextType > ( {
23+ contextLink : null ,
24+ contextRouter : null ,
25+ useContextRouteParams : ( ) => ( { } ) ,
26+ } )
Original file line number Diff line number Diff line change 1+ import { Link as ExpoLink } from 'expo-router'
2+ import type { UniversalLinkProps } from './Link.types'
3+
4+ /* --- <Link/> --------------------------------------------------------------------------------- */
5+
6+ export const Link = ( props : UniversalLinkProps ) => {
7+ // Props
8+ const {
9+ children,
10+ href,
11+ style,
12+ replace,
13+ onPress,
14+ target,
15+ asChild,
16+ push,
17+ testID,
18+ nativeID,
19+ allowFontScaling,
20+ numberOfLines,
21+ maxFontSizeMultiplier
22+ } = props
23+
24+ // -- Render --
25+
26+ return (
27+ < ExpoLink
28+ href = { href }
29+ style = { style }
30+ onPress = { onPress }
31+ target = { target }
32+ asChild = { asChild }
33+ replace = { replace }
34+ push = { push }
35+ testID = { testID }
36+ nativeID = { nativeID }
37+ allowFontScaling = { allowFontScaling }
38+ numberOfLines = { numberOfLines }
39+ maxFontSizeMultiplier = { maxFontSizeMultiplier }
40+ >
41+ { children }
42+ </ ExpoLink >
43+ )
44+ }
45+
Original file line number Diff line number Diff line change 1+ export { Link } from './Link.core.native'
File renamed without changes.
Original file line number Diff line number Diff line change 1- import { Link as ExpoLink } from 'expo-router '
1+ import React from 'react '
22import type { UniversalLinkProps } from './Link.types'
3+ import { CoreContext } from '../context/CoreContext'
34
45/* --- <Link/> --------------------------------------------------------------------------------- */
56
67export const Link = ( props : UniversalLinkProps ) => {
7- // Props
8- const {
9- children,
10- href,
11- style,
12- replace,
13- onPress,
14- target,
15- asChild,
16- push,
17- testID,
18- nativeID,
19- allowFontScaling,
20- numberOfLines,
21- maxFontSizeMultiplier
22- } = props
8+ // Context
9+ const { contextLink : ContextLink } = React . useContext ( CoreContext )
2310
24- // -- Render --
25-
26- return (
27- < ExpoLink
28- href = { href }
29- style = { style }
30- onPress = { onPress }
31- target = { target }
32- asChild = { asChild }
33- replace = { replace }
34- push = { push }
35- testID = { testID }
36- nativeID = { nativeID }
37- allowFontScaling = { allowFontScaling }
38- numberOfLines = { numberOfLines }
39- maxFontSizeMultiplier = { maxFontSizeMultiplier }
40- >
41- { children }
42- </ ExpoLink >
43- )
11+ // Render
12+ return < ContextLink { ...props } />
4413}
4514
Original file line number Diff line number Diff line change 1+ import { useLocalSearchParams } from 'expo-router'
2+ import type { UniversalRouteScreenProps } from './useRouteParams.types'
3+
4+ /** --- useRouteParams() ----------------------------------------------------------------------- */
5+ /** -i- Gets the route search and query params on both web and mobile */
6+ export const useRouteParams = ( routeScreenProps : UniversalRouteScreenProps ) => {
7+ const { params, searchParams } = routeScreenProps
8+ const expoRouterParams = useLocalSearchParams ( )
9+ return {
10+ ...params ,
11+ ...searchParams ,
12+ ...expoRouterParams ,
13+ } as typeof expoRouterParams
14+ }
Original file line number Diff line number Diff line change 1+ export { useRouteParams } from './useRouteParams.core.native'
Original file line number Diff line number Diff line change 11import type { UniversalRouteScreenProps } from './useRouteParams.types'
2+ import type { useLocalSearchParams } from 'expo-router'
23
3- /** --- useRouteParams() -------------------------------------------------------------- */
4+ /** --- useRouteParams() ----------------------------------------------------------------------- */
45/** -i- Gets the route search and query params on both web and mobile */
56export const useRouteParams = ( routeScreenProps : UniversalRouteScreenProps ) => {
67 const { params, searchParams } = routeScreenProps
7- return { ...params , ...searchParams }
8+ return { ...params , ...searchParams } as ReturnType < typeof useLocalSearchParams >
89}
You can’t perform that action at this time.
0 commit comments