React Portability Patterns
git merge with/portability-patterns
Plugin features when merged
- Make Expo for Web work again for pages that use
Image
,Link
oruseRouter()
- Provide you with patterns and knowhow to enable reuse of any component outside of Next or Expo
What are “React Portability Patterns”?
Watch this video to know all about the why and how, as explained by Jack Herrington:
What do portability patterns solve?
Typically, in Universal React Setups you had to choose between Next.js or Expo for Web to build the web version of your app. The reason is that the Next.js router and components like Link are pretty incompatible.
e.g. just slapping .web.tsx
on a Next.js specific version of Link.tsx
would work great in Next.js… but break the screen or component when opening it with Expo for Web, since using any of the Next.js router hooks or components expect its content to be mounted as well. Which is never the case when rendering web with Expo. You might, for example, have experienced similar issues when trying to render components in Storybook.
How do portability patterns work?
The trick is to not split implementations on the web or native level, but on the rendering framework level.
The only real way to do this, as far as I know, was to use React’s context API to:
- Define the types for each part of your API you want to be portable in 1 single
.types.ts
file - Build both an Expo & Next compatible
Link
component &useRouter()
hook that each implement these same types - In your Expo Router app dir layout provider, pass the Expo compatible
Link
&router
object in context - In your Next.js app dir layout provider, pass the Next compatible
Link
&router
object in context - Have your universal
useRouter()
hook use therouter
object from context - Have your universal
Link
component pass props to theLink
component from context - Only use the context enabled
useRouter()
&Link
components
What do portability patterns enable?
Well, to take things further and with the right effort, you could theoretically apply these same steps to:
- Make a mocked context provider for seamless Storybook Docs support without the need for plugins
- Render your app using e.g. Remix or some custom setup with Vite
- Pick either Expo for Web or Next.js to build an Electron-based desktop version
- …
Whether you want to reuse components and screens in Expo, Next, Remix or a smart fridge, if you have enough time and the right docs at hand, the possibilities are almost endless 👀
Enjoy!
Disclaimer
with/portability-patterns
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 #3 - React Portability Patterns 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.