Responsive UIs in React Native
Recently, I published a premium starter kit for RN named React Native DO. Like many React Native apps on the market today, it was designed to work only with the device in portrait orientation. Quickly, I received feedback asking to support the landscape orientation as well.
React Native enables you to build native apps using web development skills. And yet, in web development, we never assume fixed dimensions. In React Native however, we overwhelmingly do the opposite. In fact, most libraries built by the community assume a static static size for the app window. This is true even for libraries that address the topic of responsive design: they assume that the dimensions of the window won’t change over time. To address this issue, I built the react-native-responsive-ui package.
Listening to Dimension Changes
You don’t need an extra native dependency such as react-native-orientation to listen to orientation changes in React Native. This can be achieved with the Dimensions.addEventListener() method. In the example below, we listen to dimension changes within a React component. The app window dimensions are attached to the state so the component will re-render on every update. Finally, we need to stop listening when the component will unmount.
Responsive Components
Dimensions of the app window might update because of device orientation has changed or because the screen of the device has split with another app. On the web, responsive design is done declaratively with CSS. In React Native, the dimensions of the window need to be added to the state of the component. This is a bit less elegant than and has some performance impact since the component needs to re-render on every changes. But is it unlikely to lead to a bad user experience: when changing the device orientation or when splitting the device’s screen, frames that are dropped due to the re-rendering of the components shouldn’t be noticeable.
The react-native-responsive-ui package provides a decorator named responsive that can be extended in order to react on dimension changes. In the example below, we refactored the our previous code snippet to use this new decorator.
Media Queries
The react-native-responsive-ui package provides a component that renders its children only if certain conditions are met. In the example below, we render the Logo component only if the height of the app window has a minimum size of 450dp and if the device orientation is in portrait mode.
StyleSheets
The ResponsiveStyleSheet module returns a stylesheet that merges multiple media queries. Unlike the StyleSheet module, responsive styles must be built when rendering a component. And the component must render on every dimension change. This is achieved by extending the ResponsiveComponent class. In the example below, we display a list of buttons. If the device is in landscape mode, the buttons are stacked horizontally and stretched to occupy the full width of the container. In portrait mode, they are stacked as a vertically and stretched horizontally.
The Tip of the Iceberg
Hopefully you will find the previous code snippets useful. They only cover the bare minimum to make your React Native visual design scale. On the web, using only relative units such as % or em are a great way to your visual design fit any screen size. But in RN, there is only a single unit available and you need to compute relative sizes yourself.
Styling in React is a very hot topic and should be even hotter for React Native. There doesn’t seem to a silver bullet solution yet for “regular” styling, let alone responsive styling. There are many interesting projects emerging however. Shoutem theme is one worth mentioning. Their goal is to decouple the styling of a component from its implementation. And since requirements for styling components are increasingly growing, I find their approach very promising. It would be interesting to see in the future if this project will offer the possibility re-style components on dimension changes.
That’s All
Et voilà! I hope this story might be helpful to you, and I look forward to reading your feedback.
Looking for a Premium Stater Kit?
Checkout React Native Sketch Elements, the most comprehensive React Native starter kit.