A Tour of React Native — Part 1: The Visuals
You’re sold on React Native, but how much do you need to learn to build a “normal” app? This 3-part guided tour will help with that answer.
Congratulations!
You were cautious. You weighed the pros and cons. You’re ready to get started. Now what?
¯\_(ツ)_/¯
How hard is it to actually build something? How much do I need to learn?
The goal of this 3-part article is to answer those questions. To survey the React Native landscape. To seek out new life and new civilizations.
We’ll slot everything into these 3 categories:
- Visuals— things you see on the screen
- Logic — things that make your app work
- Tools — things you use to build your app
On to part 1! The Visuals!
What’s Inside?
React Native has many parts.
The pieces like WebView and MapView are immediately recognizable. You know exactly what to make with them.
You’ll also see things like DatePickerIOS, ProgressBarAndroid and SliderIOS. These are platform-specific. If cross-platform mobile apps is on your radar (spoiler: it is), then steer clear of these (for now).
Other pieces (like View, Text, Image, ScrollView, and ListView) are what you’re going to use the most.
Because you’ll use these to…
Build Your Own Components
React Native doesn’t ship with a Button! You have to build it yourself.
A “button” can be just a Text inside a TouchableOpacity with an onPress event. Or maybe you want to stick an Image in there too.
And, since we’ve already raised our pitchfork, React Native also doesn’t ship with a LoginForm!
Woah, okay, that was a big jump from a missing button component. Well, that’s my point. A LoginForm is just two Text components, two TextInput components, and that awesome Button you made two paragraphs ago.
Your app will be filled with components you make. Some of them will show up in multiple places (like your Button) and some will be screens (like your LoginForm).
The Component Class
The Component class in React is how you’ll most likely be building your components. It’s not the only way as Dale Jefferson points out, but the most popular.
You’ll build them using JSX (most likely) inside your render() function.
Lifecycle Callbacks
React-hosted components have their own lifecycle callbacks. There is componentWillReceiveProps() for when your component acquires new properties, shouldComponentUpdate() for dodging re-renders, componentDidMount() when it first comes to life, and several other important ones.
Props
Learn how to communicate back and forth between your components with props and events. PropTypes will help you define the interface of your components as you build them.
If there’s one thing you take away from this article: as much as you can, design your components to be configured through props.
It’s hard to express this without code and a bigger example, but props is the cornerstone of building clean large apps.
State
If your UI components need to manage their own UI State, read up on state and how calling setState() will trigger your render(). In the bigger picture, state is usually managed elsewhere (spoiler: redux in part 2 of this series), but for micro UI-based state, React Native has you covered.
Styling & Layout
To make your app look nice; you’ll be using styles.
StyleSheets
These are essentially just object literals.
const styles = StyleSheet.create({
evenStripe: { backgroundColor: 'red', height: 20 },
oddStripe: { backgroundColor: 'white', height: 20 },
paragraph: { fontFamily: 'Comic Sans', color: 'green' },
error: { color: '#ff0000' }
})
You plug them into your views.
<View style={ styles.evenStripe } />
<View style={ styles.oddStripe } />
And you can use a bunch at a time (they merge and overwrite from right to left).
<View style={ [styles.paragraph, styles.error] } />
Organization
My colleague Gant Laborde recommends putting your styles into separate stylesheet files. I disagreed with him. I was wrong. Give it a shot. It really cleans things up.
Another idea is to tuck your theme-related constants away. Great for fonts, colors, metrics, and dimensions.
// Colors.js
export default {
primary: '#f00ba4',
complementary: '#101010'
}// Metrics.js
export default {
screenMargin: 20,
buttonHeight: 40
}
Flexbox
This is the spot where we get spoiled.
Layout is a hard thing. Android has its own (multiple) layout strategies. iOS… well, let’s just say, they finally got it right with UIStackViews.
With Flexbox, we don’t need to care.
You can flex horizontal (like piano keys) or vertical (like a delicious hamburger).
However you flex, you can control the children’s alignment too. You’ll wrestle with justifyContent (on-axis) and alignItems (off-axis) quite a bit. It’s a right of passage though.
There are many styling options. You don’t need to know them all.
You can also use position: ‘absolute’ if you need to dock or overlap.
Hierarchy
We don’t have z-index, but you can use the position in your render structure to simulate it. The last element defined will have precedence.
You might find it a little tricky to keep the component hierarchy visualized in your head once your containers start having containers.
Humans Doing Things
If only every app was read-only. Sigh.
Touchables
If you need a basic button behaviour, look at the Touchable components: TouchableOpacity, TouchableWithoutFeedback, TouchableHighlight, and TouchableNativeFeedback.
PanResponder
If you need to start doing more complex things like swipe detection and dragging, PanResponder can help.
At last count, there are 89 different methods you implement to get the behaviour you want. It actually feels intimidating until you write one, however, it’s really not that bad.
TextInput
TextInput maps to the native TextView and UITextField components. It’ll bring up the keyboard. Lots of options for choosing they keyboard type and responding to events like focus, change and submit.
DeviceEventEmitter
When a keyboard pops up, it’ll overlap your view. This sucks if you’re typing in a field that becomes covered by the crazy keyboard. You can subscribe to DeviceEventEmitter to let you know when the keyboard shows and hides. That way you can handle view repositioning appropriately.
GPS
Out of the box, React Native gives you GPS support. Use the getCurrentPosition() to get your user’s coordinates. If it is the first time your app is being used, the permissions will be acquired from the user first.
Animation
You’ve got a couple of options for animating views.
Animated
The Animated API provides a way to move views around with nice easing effects. Despite driving the animations from JavaScript, the performance is very acceptable.
The gist:
- create a Value
- configure it — duration, starting value, ending value
- kick it off
- re-render the view as fast as you can
- map the values mid-render to stylesheet options (height for example)
There’s more to it (easing & interpolation, x/y values), but it’s very approachable.
LayoutAnimation
A simpler way to do animation is to use LayoutAnimation. With your view, you take its frame, give it a new frame, and LayoutAnimation will take care of making transition happen.
Magical. Justin Poliachik has more to say.
React-Native-Animatable
Another option for animation is to use this great 3rd party library which ships with a bunch of presets. It piggy-backs on Animated and provides a surprising amount of flexibility.
We’ve had great success using this. It’s well worth taking 20 minutes to try out!
InteractionManager
Its not quite animation, but a good time to talk about it.
So, you’ve got janky animations. Okay. Why? Well, the short answer is you’re doing too much work on the JavaScript thread.
When you’re ready to fix some of this, you can use the InteractionManager to defer some of the CPU-heavy code until your animations finish up. It’s a great first-step for a smooth user experience.
Screen Flow
After building your screens, how do you string them together into an app?
If you’re using to iOS development, you might use a UINavigationController to manage your view stack. There’s even a React Native component for that. However it’s not Android compatible.
So what most people do is either use Navigator or make their own and abandon it on Github. Sorry for the snark; it’s actually a really tough problem to solve.
Late Breaking Good News: A new Navigator is currently in the works and should be arriving soon!
Navigator
This component ships with React Native and provides a mechanism to flow from screen to screen. You pass it a “route” which is just an object literal and a function that will render the appropriate component for that route (renderScene()).
What it gives you is a way to drill through screens complete with configurable…
Transitions & Gestures
When you push a new scene (aka component aka screen) on the navigator’s stack, you’ll see a nice sliding transition. The old screen will fade out and be replaced by the new screen.
This is all configurable. There are presets for Android-style, iOS style, and in all 4 directions. It’s beautiful.
Also available are gestures. For example, swiping back on the left edge of the screen on iOS is now a thing. And out of the box, Navigator supports this.
Look at the Navigator’s configureScene() callback to tweak.
Routes
Routes are just object literals. When you push a route onto the navigator, it’ll called both renderScene() and configureScene() to make the right thing happen.
One pattern we’ve used at Infinite Red is to start packing some information into our routes that renderScene() and configureScene() will use. For example, “show navigation bar”, or “navigation bar height”, or “show logo”. It becomes a little more flexible to make many screens/scenes like this.
Route Stack
When you push routes onto your navigator they go into a stack. This stack can be managed by calling pop() or popToTop() or replace() or other goodies.
Keep in mind, past screens are still in memory, so mind your step.
That Really-Weird-Navigator-Bar-Route-Mapper Thing
By default, the Navigator comes with a NavigationBar. This is what you’re used to seeing on iOS apps at the top with the back button.
This bar is configurable, but it’s a bit quirky. You’ll end up creating an awkward NavigatorBarRouteMapper that exposes a few objects via LeftButton, RightButton, and Title.
It’s good for most uses actually. I hit the limits trying to customize the background with an image and also trying to prevent transition animations. But that’s just me and sometimes I struggle making sandwiches.
Modal Dialogs
There’s a few ways to handle this. If it is full screen, I’d recommend just using navigator.
If its not full screen, you could use the Modal component that comes with React.
And There We Have It
So that’s a quick tour of the front-facing React Native stuff.
Although there are a lot of moving parts, I’m finding none of them very difficult.
In part 2, we’ll cover the non-visual parts of your app, the things that happen after you click that button, or download that data, or show that list.
I’m @skellock on Twitter. Press the ❤ button below to beam up.