3 Things I Wish I Knew Before Migrating to React Native and Integrating Expo for the First Time

Eugene Lerman
Remitly Israel (formerly Rewire)
5 min readOct 14, 2020
Photo by Christopher Gower on Unsplash

If you’re like us, you may be facing problems with integrating Expo for mobile in an existing web codebase, dealing with CSS/StyleSheet incompatibility issues, or seeing ‘invalid hook call’ errors when running Storybook for React Native. React and React Native both allow developers to write reusable logic and share it across multiple projects and platforms. What happens when you transition from a web-centric React environment to a more Mobile-oriented React Native approach while still maintaining support for a full-fledged web app? That’s exactly what we found out when we started working on our next-generation application.

At Rewire, we are currently in the process of moving from a traditional (read: legacy), thick gumbo of Angular 1.x, Ionic/Cordova, React and React Native components (with the excellent react-native-web library to help us render these on the web), to a modern crême-brûlée of a React Native mobile application.

In this short blog post, we’d like to share with you solutions to some of the pain points we encountered along the way.

Let’s go!

1. Integrating Expo into an existing codebase

We quickly decided to use Expo as our native app platform and run Storybook for React Native for testing and interacting with our components on-device. Most of Expo’s FAQ and Getting Started documentation deals with setting up a fresh project in a new repository, but our React Native components repository existed before we began using Expo. We had to figure out how to get our existing codebase to play nice.

We did start with the FAQ. While a little sparse in detail, it is at least a nudge in the right direction.

Ultimately, after a valiant battle of configuration and settings was waged, a colleague stumbled upon this great example in Expo’s Github repository, containing a very detailed guide + sample code that we used as a reference when adding Expo to our code.

2. Incompatible CSS

React Native uses Yoga as its layout engine, and StyleSheet as an abstraction that’s similar to CSS stylesheets. This is great as it allows developers who are already familiar with web technologies to skip the learning curve. Having said that, you do not have full parity for CSS in React Native and some of these differences may cause unexpected issues.

2.1 `position: absolute` makes your components un-press-able

Let’s say you have a <FloatingButton/> component you'd like to always render at the bottom-right corner of your application. Seems like the perfect use-case for absolute positioning, right?

Turns outs <FloatingButton/>will sometimes be rendered beneath other components in your layout, which may cause frustration for you and your users. This is actually a known bug in React Native 🐞😱.

One quick & dirty trick you can try to mitigate this is to add zIndex: 1(or higher) to your component’s style property. This will make sure it is positioned above other elements it might otherwise overlap with. Presto!

2.2 borderRadius doesn’t accept percentages in React Native

Say we want to create this little oval shape, and have it scale correctly across different screen sizes. In our application, we do something like this to give the user a guide for positioning their face when taking a selfie.

With CSS, this is pretty trivial stuff. However, once you take away one parameter it becomes considerably trickier.

Here is our simple standard CSS:

So, how do we get that awesome oval shape when borderRadius only accepts numeric values? transform, scaleX and scaleY to the rescue:

What about the height and width properties? Basing the values on the size of the screen, and using relative scaling (via the transform above) will result in the oval shape we need.

First, get the width and height of the screen by using the onLayout prop of our containing View. Use the smaller value of the two and assign it to borderRadius, using half of that for the width and height. The result is a perfect circle and, after scaling, will result in our nice oval:

We can keep our code clean and make sure this remains updated as the screen rotates or otherwise changes size by using React Hooks.

3. storybook-react-native “Invalid hook call” error

At Rewire, we like to keep up with the latest cutting-edge technology and we like standards that allow the whole industry to move forward. So, it is no surprise we prefer to use Component Story Format for our Storybook stories (it’s over a year old at this point, so it’s not even that cutting-edge anymore — more like the cutting-adjacent). As it turns out, that put us a bit ahead of Storybook for React Native.

Consider the following snippet:

Seems innocuous enough, but if we go ahead and try to run this, we see the following error:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

We did not find much to go on when scouring the web for solutions, but with a little time, effort, and elbow-grease we were able to figure out the answer. Basically, we need to wrap our exported components with a function instead of directly passing them through by reference. Luckily, the fix couldn’t be simpler. We just change the last line of the previous code sample to the following:

Problem solved

Our little adventure ended up teaching us a lot. We hope sharing the issues we encountered and the solutions we implemented can help you save time and effort. Please let us know if it did in the comments, and definitely share what additional problems you ran into on your React Native journey and how you resolved them.

Rewire’s mission to help migrants build a better, more financially secure future is always at the forefront. It helps us focus on what’s important and get creative when we encounter technical conundrums.

--

--