React and React Native: maximize the code reusability

Code reusability is important when you want to write maintainable apps. This is even more important when you are developing multiplatform apps that share a big portion of its functionality. In this article, I will tell you my experience developing a multiplatform app, for the web using React and native apps using React Native.

React and React Native: maximize the code reusability

Sharing code between different apps it’s an important reminder that architecture matters. I developed a basic Trivia Game to use as an example of how you can structure your code if you are building apps with a similar stack: TypeScript, React, React Native, Redux, Sagas, and Expo. The task of structure and share code between these technologies could have some pain points so I think that could be useful to have this info at hand.

Before start, give trivia a chance

Before submerging ourselves in the explanation part, maybe you give the web app a chance and play with the trivia: https://triviagame.matiasbenedetto.now.sh.

If you want to leapfrog the explanations you can go straight to the codebase: https://github.com/matiasbenedetto/trivia

Architecture:

As I said, the codebase organization was planned to have a large portion of the code shared between the web and native apps to avoid code repetition and make app development more efficient, maintainable and sustainable.

Shared code

The shared code that lives in /main/src contains all the logic, API data fetching, connected components, and state management tasks and is re-utilized across both apps. All the common dependency packages for both platforms as react are listed in the /main/package.json file.

Platform-specific code

The code that lives in /main/apps/web and /main/apps/native is unique for each kind of platform. This code is related to the navigation and presentational parts of the apps that should be managed differently for each platform.

The specific package dependencies for web (as react-router react-dom, node-sass) are listed on /main/apps/web/package.json. The specific package dependencies for native apps (as expo, react-native and react-navigation) are listed on /main/apps/web/package.json. To access de common dependencies npm will look upper in the directory hierarchy.

Getting over the pain points

For both Web and Native, the project relays on npm link to link the dependency of the main module. npm link creates a symlink between the main module and the platform module’s node_modules folder, so the developer can work with all the tooling working as Hot-Reloading and IntelliSense.

Using this approach you can import any exported module from your main shared app in your platform-specific app (React or React Native) with an import as the main module was a normal npm installed package. For example to import a connected component:
import ConnectedTrivia from ‘trivia-main’.

There is a problem related to npm that consist of the erasing of the symbolic link after installing a new dependency with npm install. So don’t forget to npm link your main module again after installing any new package.

Even though for react-native npm link is not enough because of the code bundler used by react-native and Expo. Metro bundler is not able to follow symlinks so you should add a specific config for the bundler to know which folders should use to compile the code. This config lives in main/apps/native/metro.config.js.