Sharing code between React Web and React-Native Mobile apps

A shared codebase between platforms will result in quicker development time, cleaner code and easier maintenance.

Many businesses have a website as well as Android and iOS mobile apps. Usually, these projects have been developed at different stages, first the need for a website, then later on a mobile app was added. Even though the different platforms may look slightly different, the core business logic is usually much the same. This can present problems.

Each time new functionality needs to be added to the website and mobile apps, the changes need to be made to three different codebases for each of the different platforms. This is usually across multiple development teams based on the different programming languages used by each platform.

The need for both web and mobile presence at first launch is now much more frequent, and it is in this scenario where we have the opportunity to start the architecture for the solution from scratch.

Following on from our blog post about choosing React-Native for your mobile app framework, we will now go on to explain why we would choose React with React-Native for a website and mobile app combination.

The benefits of code sharing

The goal is to achieve a consistent experience across multiple platforms iOS, Android and Web. Why the combination of React and React-Native? Code re-use is a primary motivator. If using React and React-Native, we are actually able to share the most important code with the potential to have it all in one code-base then render it to multiple front-end applications. This speeds up development time, prevents duplicated code, and minimises the need to spread the effort across multiple development teams.

What code can be shared?

Let’s go over the basic components that make up a React/React-Native app. We separate UI from business logic by separating presentational components from container components. The code that can be shared between the platforms will be the container components, this is where the important code lies.

Presentational component

Functions that render components, with no state management.

Primarily used for layout and styling.

Should be platform-specific.

Container component

How things work, providing data and behaviour.

Includes state management and business logic.

Can be multi-platform.

Essentially, the container components should have the business logic to be shared across the different platforms, then the views styled in their platform specific variants.

But what if we want different interactions on different platforms? For example, when a user taps a cell in the app, we would want to redirect them to another screen, but this may not make sense on the web. Although actions are part of the shared code, we are able to implement the call-backs for the different interactions on each platform as necessary.

We will now go on to explain more about what will be platform specific, and what will be cross-platform by use of an example.

Cross-platform example

There are three types of component:

Root (platform-specific).

Cross-platform container component.

Platform-specific presentational component.

The following image shows both a mobile app and mobile responsive website with shared code, and the red, purple and green lines show the different types of component in use.

Mobile and desktop

Platform-specific root (red line)

The outermost root component is platform-specific. This is where the navigation will be set for the mobile app.

Cross-platform container component (purple line)

For the followers list container, this is where we have the business logic and our data-fetching. The fetched data is then passed as a prop to the presentational component. This container component is shared across all platforms.

Platform-specific presentational component (green line)

The followers list data is received as a prop into the presentational component, and rendered for the specific platform. The reason these components need to be platform specific is due to the difference in components used in the layout e.g <div> versus <view> as well as slight difference in styling e.g style={} versus CSS.

General architecture rules

For cross-platform components:

Don’t import react-native or react-dom.

Don’t import platform specific components, but have them passed-in instead.

Do import other cross-platform components.

For platform-specific components:

Do import react-native or react-dom.

Do import other platform specific components.

Do import other cross-platform components.

One code-base or two?

It is entirely possible to have one single code-base for both the React and React-Native apps, but it may be easier to have the shared code in a package which can be set as a dependency inside each of the projects. The best choice will vary depending on factors such as the size of the project, development team structure and/or personal preference. Different packagers are also necessary for the different platforms, for example you may use Web Pack for React, Metro for React-Native, as well as Jest for testing.

In conclusion

We can reduce the cost of writing our website and mobile applications by sharing the codebase between a React Native mobile app and a React website, particularly when developing a website and mobile apps with shared functionality simultaneously. The resulting code is cleaner and easier to maintain, with less effort spread across multiple development teams.