Learn the Basics
React Native is like React, but it uses native components instead of web components as building blocks. So to understand the basic structure of a React Native app, you need to understand some of the basic React concepts, like JSX, components, state
, and props
. If you already know React, you still need to learn some React-Native-specific stuff, like the native components. This tutorial is aimed at all audiences, whether you have React experience or not.
Let's do this thing.
Hello World
In accordance with the ancient traditions of our people, we must first build an app that does nothing except say "Hello world". Here it is:
import React, { Component } from 'react';
import { Text, View } from 'react-native';
export default class HelloWorldApp extends Component {
render() {
return (
<View>
<Text>Hello world!</Text>
</View>
);
}
}
What's going on here?
Some of the things in here might not look like JavaScript to you. Don't panic. This is the future.
First of all, ES2015 (also known as ES6) is a set of improvements to JavaScript that is now part of the official standard, but not yet supported by all browsers, so often it isn't used yet in web development. React Native ships with ES2015 support, so you can use this stuff without worrying about compatibility. import
, from
, class
, and extends
in the example above are all ES2015 features. If you aren't familiar with ES2015, you can probably pick it up just by reading through sample code like this tutorial has. If you want, this page has a good overview of ES2015 features.
The other unusual thing in this code example is <View><Text>Hello world!</Text></View>
. This is JSX - a syntax for embedding XML within JavaScript. Many frameworks use a special templating language which lets you embed code inside markup language. In React, this is reversed. JSX lets you write your markup language inside code. It looks like HTML on the web, except instead of web things like <div>
or <span>
, you use React components. In this case, <Text>
is a built-in component that just displays some text and View is like the <div>
or <span>
.
Components
So this code is defining HelloWorldApp
, a new Component
. When you're building a React Native app, you'll be making new components a lot. Anything you see on the screen is some sort of component. A component can be pretty simple - the only thing that's required is a render
function which returns some JSX to render.
Props
Most components can be customized when they are created, with different parameters. These creation parameters are called props
.
For example, one basic React Native component is the Image
. When you create an image, you can use a prop named source
to control what image it shows.
import React, { Component } from 'react';
import { AppRegistry, Image } from 'react-native';
export default class Bananas extends Component {
render() {
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};
return (
<Image source={pic} style={{width: 193, height: 110}}/>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => Bananas);
Notice that {pic}
is surrounded by braces, to embed the variable pic
into JSX. You can put any JavaScript expression inside braces in JSX.
Your own components can also use props
. This lets you make a single component that is used in many different places in your app, with slightly different properties in each place. Just refer to this.props
in your render
function. Here's an example:
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
export default class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => LotsOfGreetings);
Using name
as a prop lets us customize the Greeting
component, so we can reuse that component for each of our greetings. This example also uses the Greeting
component in JSX, just like the built-in components. The power to do this is what makes React so cool - if you find yourself wishing that you had a different set of UI primitives to work with, you just invent new ones.
The other new thing going on here is the View
component. A View
is useful as a container for other components, to help control style and layout.
With props
and the basic Text
, Image
, and View
components, you can build a wide variety of static screens. To learn how to make your app change over time, you need to learn about State.
State
There are two types of data that control a component: props
and state
. props
are set by the parent and they are fixed throughout the lifetime of a component. For data that is going to change, we have to use state
.
In general, you should initialize state
in the constructor, and then call setState
when you want to change it.
For example, let's say we want to make text that blinks all the time. The text itself gets set once when the blinking component gets created, so the text itself is a prop
. The "whether the text is currently on or off" changes over time, so that should be kept in state
.
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Blink extends Component {
constructor(props) {
super(props);
this.state = {isShowingText: true};
// Toggle the state every second
setInterval(() => {
this.setState(previousState => {
return { isShowingText: !previousState.isShowingText };
});
}, 1000);
}
render() {
let display = this.state.isShowingText ? this.props.text : ' ';
return (
<Text>{display}</Text>
);
}
}
export default class BlinkApp extends Component {
render() {
return (
<View>
<Blink text='I love to blink' />
<Blink text='Yes blinking is so great' />
<Blink text='Why did they ever take this out of HTML' />
<Blink text='Look at me look at me look at me' />
</View>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => BlinkApp);
In a real application, you probably won't be setting state with a timer. You might set state when you have new data arrived from the server, or from user input. You can also use a state container like Redux or Mobx to control your data flow. In that case you would use Redux or Mobx to modify your state rather than calling setState directly.
When setState is called, BlinkApp will re-render its Component. By calling setState
within the Timer, the component will re-render every time the Timer ticks.
State works the same way as it does in React, so for more details on handling state, you can look at the React.Component API. At this point, you might be annoyed that most of our examples so far use boring default black text. To make things more beautiful, you will have to learn about Style.
Style
With React Native, you don't use a special language or syntax for defining styles. You just style your application using JavaScript. All of the core components accept a prop named style
. The style names and values usually match how CSS works on the web, except names are written using camel casing, e.g backgroundColor
rather than background-color
.
The style
prop can be a plain old JavaScript object. That's the simplest and what we usually use for example code. You can also pass an array of styles - the last style in the array has precedence, so you can use this to inherit styles.
As a component grows in complexity, it is often cleaner to use StyleSheet.create
to define several styles in one place. Here's an example:
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
export default class LotsOfStyles extends Component {
render() {
return (
<View>
<Text style={styles.red}>just red</Text>
<Text style={styles.bigblue}>just bigblue</Text>
<Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
<Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigblue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => LotsOfStyles);
One common pattern is to make your component accept a style
prop which in turn is used to style subcomponents. You can use this to make styles "cascade" the way they do in CSS.
There are a lot more ways to customize text style. Check out the Text component reference for a complete list.
Now you can make your text beautiful. The next step in becoming a style master is to learn how to control component size.
Height and Width
A component's height and width determine its size on the screen.
Fixed Dimensions
The simplest way to set the dimensions of a component is by adding a fixed width
and height
to style. All dimensions in React Native are unitless, and represent density-independent pixels.
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
export default class FixedDimensionsBasics extends Component {
render() {
return (
<View>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} />
<View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} />
</View>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => FixedDimensionsBasics);
Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions.
Flex Dimensions
Use flex
in a component's style to have the component expand and shrink dynamically based on available space. Normally you will use flex: 1
, which tells a component to fill all available space, shared evenly amongst each other component with the same parent. The larger the flex
given, the higher the ratio of space a component will take compared to its siblings.
A component can only expand to fill available space if its parent has dimensions greater than 0. If a parent does not have either a fixed width
and height
or flex
, the parent will have dimensions of 0 and the flex
children will not be visible.
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
export default class FlexDimensionsBasics extends Component {
render() {
return (
// Try removing the `flex: 1` on the parent View.
// The parent will not have dimensions, so the children can't expand.
// What if you add `height: 300` instead of `flex: 1`?
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'powderblue'}} />
<View style={{flex: 2, backgroundColor: 'skyblue'}} />
<View style={{flex: 3, backgroundColor: 'steelblue'}} />
</View>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => FlexDimensionsBasics);
After you can control a component's size, the next step is to learn how to lay it out on the screen.
More Info
For more info (and the real documentation), hop on over to the official React Native documentation!