by

Any app written with React Native in JavaScript consist of at least one component.

That’s how your app looks like if we break everything down to components.

Defining Component

To define a component we need to import React and Component classes from react module.

import React, { Component } from 'react’;

Then import other components if we’re going to use any in our component.

import {
  Text
} from 'react-native';

And define our component class by extending Component class.

class AwesomeComponent extends Component {
  ...
}

Exporting and Importing Components

To export out component, so other components can import and use it we need to add export before class declaration.

export class AwesomeComponent extends Component {

We can also export our components as a default one, using export default.

export default class AwesomeComponent extends Component {

Imagine if you had a component we just defined in a file called AwesomeComponent.js, then you could import it in another file by either importing it by component and file names

import AwesomeComponent from './AwesomeComponent';

or by importing default and assigning any name to it

import { default as AnyName } from './AwesomeComponent';

There can only be one default class exported per file. But you can export as many classes and variables and import them in other files as you want.

Render Method

Every React Native component has to have at least one method called render. This method gets executed when your component needs to be rendered on the screen.

render() {
  return <Text>That's a component</Text>;
}

JSX

In order to use other components in render method we need to use JSX tags. That means we just need to put component name in angle brackets like so <Component />, if component does’t have any children components, or use open <Component> and close </Component> tag with children components in between. You can also pass any number of properties (or props) to a components <Component prop={value} anotherProp="string value" />.

Let’s take a look at the example.

render() {
  return <Text>That's a component</Text>;
}

In the code above we return <Text>That's a component</Text> component in render method, which means that when React Native renders our component it goes to Text controller, invokes its render method and passes this text That's a component between <Text> tags as a prop to Text component.

AwesomeComponent.js

Let’s create a file called AwesomeComponent.js for our component and put it all together.

import React, { Component } from 'react';
import {
  Text
} from 'react-native';

export default class AwesomeComponent extends Component {
  render() {
    return <Text>That's an awesome component</Text>;
  }
}

It’s a good practice to name your files the same as default exported components in those files.

Methods

You can have other methods besides render in a component. For example, you can define text method

text() {
  return <Text>That's an awesome component</Text>
}

And reference it in render method by using this, which references the component itself.

render() {
  return this.text();
}

State

Components in React Native can also have state for the data that changes over time. To define component state use state = { key: value } notation. That’s just a key-value object with one or more comma separated key-values.

class AwesomeComponent extends Component {
  state = {
    counter: 1
  }
  render() { ... }
}

To access data in the state use this.state.KEY.

render() {
  return (
    <Text>
      The counter is {this.state.counter}
    </Text>
  );
}

Notice how we put {this.state.counter} in curly braces. That’s required when you want to inject any JavaScript expression, including state values, other variables or methods and conditions into JSX tags.

To change state data we can use this.setState({ KEY: VALUE })

updateCounter() {
  this.setState({ counter: 2 });
}

Whenever you update the state your component gets re-rendered automatically.

Props

You can pass any number of props from parent component down to child component

render() {
  return (
    <Text numberOfLines={1}>
      That's an awesome component
    </Text>
  );
}

In this example we passed value of 1 to a prop named numberOfLines.

All of the props passed to a components are stored in this.props object. And we can access those props in any of Text component methods.

render() {
  const lines = this.props.numberOfLines;
}

The text That's an awesome component that we passed between <Text> and </Text> is actually a prop as well. You can access is as this.props.children

It’s a good practice to define props that you’re going to use in beginning of your method as const variables.

render() {
  const lines = this.props.numberOfLines;
  const children = this.props.children;
}

You can make it a little bit shorter by keeping first const and omitting all later ones and using commas to separate different declarations.

render() {
  const lines = this.props.numberOfLines,
    children = this.props.children;
}

To make it even more shorter you can do

render() {
  const { numberOfLines, children } = this.props;
}

Which means get numberOfLines and children properties of this.props object and turn them into constants.

You can even do this inside render() declaration

render({ numberOfLines, children } = this.props) {
  ...
}

Nesting Components

Methods in React Native can return only one top level JSX component. Let’s say we want to return 3 different Text component as a result of render method. In this case we hate wrap those 3 component into a single one. Otherwise it would throw an error. Usually you would wrap other components into View component like so

render() {
  return (
    <View>
      // method we defined earlier, which returns JSX component
      {this.text()} 
      <Text numberOfLines={1}>
        The counter is {this.state.counter}
      </Text>
      <Text>More text</Text>
    </View>
  );
}

You can nest as many components as you want inside other components.

Final Example

Let’s put everything that we’ve learned together and create a new app to see it in action. Open Terminal App and run these commands.

react-native init LearnignComponents;
cd LearnignComponents;

Open index.ios.js file and change its content with the following code.

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class LearnignComponents extends Component {

  state = {
    counter: 1
  }

  text() {
    return <Text>That's an awesome component</Text>;
  }

  updateCounter() {
    this.setState({ counter: 2 });
  }

  render() {
    return (
      <View style={styles.container}>
        {this.text()}
        <Text numberOfLines={1}>
          The counter is {this.state.counter}
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
});

AppRegistry.registerComponent('LearnignComponents', () => LearnignComponents);

And run the app.

react-native run-ios;

And here they are. Two Text components nested inside View component. One rendered as JSX, another by text() method. And both centered on the screen inside View component, which we styled with flex: 1 to take the whole screen and instructed to center content inside id both vertically and horizontally with justifyContent: 'center', alignItems: 'center'.

I hope you enjoyed the tutorial. Subscribe to find out about new tutorials and learn how to build amazing apps!

Recommended Reading

Spread the Word