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.
Table of contents
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}.
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!
Pingback: State in React Native Components | Rational App Development()
Pingback: Universal Tab Bar in React Native | Rational App Development()