(React Native) Components, State and Props
In React world, there are three important concepts that every React Native developer should know, components, state and props. Understanding these concepts can be a little bit hard for beginners. In this article, I try to summarize the concepts briefly.
Components
Thinking about making apps in native languages, you create a screen with a bunch of UIComponents such as Button, TextField, View, ImageView etc.
The main idea of components is making those kinds of parts in separated JS files and reusing the parts wherever we want. It is easy to understand if you have experience in mobile development in native languages since it is similar to making UITableViewCell or ListViewCell in a separated file.
Here is the definition of components from the official website of React.
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. — Excerpt from React official website
There are two ways of declaring components in React world.
1. Functional Components
Functional components are declared by using JavaScript function.
const Button = ({ onPress, children }) => {
const { buttonStyle, textStyle } = styles;
return (
<TouchableOpacity onPress={onPress} style={buttonStyle}>
<Text style={textStyle}>
{children}
</Text>
</TouchableOpacity>
);
};
- Used for static data
- Cannot handle fetching data from API or taking user inputs since it’s static
- Doesn’t have state
2. Class Components
Class components are declared by using ES6 class.
import React, { Component } from 'react';class LoginForm extends Component {
state = { email: '', password: '' };render() {
return (
<View>
<TextInputView
placeholder="sample@gmail.com"
label="Email"
value={this.state.email}
onChangeText={email => this.setState({ email })}
/>
<TextInputView
placeholder="password"
label="Password"
value={this.state.password}
onChangeText={password => this.setState({ password })}
/>
</View>
);
}
}
- Used for dynamic data
- Can handle dynamic data such as fetching data, user inputs, etc
- Knows when it gets rendered to the device
(in other words, life-cycle methods can live inside)
Note:
In order to borrow a bunch of functionalities from React Component, you need extends Component
. Just like any other JSX tags, it requires importing { Component }
from React.
Notice that you have to keep the reference to React
. The reason for that is that Babel.js uses createElement()
function from React library when it converts JSX into raw JavaScript. That is how it React works under the hood. Therefore you want to write as import React, { Component } from ‘react’
, in order to keep the reference to React library itself and also import Component
out of React library.
How to decide which type of components to use?
If you need to handle fetching data or user events, class components are the only option.
If you are just handling static data, it’s better to use functional components since there would be less code in that way.
Props
Although the word “props” stands for “properties”, it looks more like attributes in HTML tags and works like arguments for functions in native languages for mobile development.
Using props, you can pass data from the parent view down to the child view. Let’s take a look at the sample code for class components again.
class LoginForm extends Component {
state = { email: '', password: '' };render() {
return (
<View>
<TextInputView
placeholder="sample@gmail.com"
label="Email"
value={this.state.email}
onChangeText={email => this.setState({ email })}
/>
<TextInputView
placeholder="password"
label="Password"
value={this.state.password}
onChangeText={password => this.setState({ password })}
/>
</View>
);
}
}
This class component takes email and password as inputs from the user.
Notice “TextInputView” is another custom component which I will show you in the explanation for “state”. For now, I just say “TextInputView” takes “value” as props. When you set props in the child view, the parent view can pass values via the props.
In this example, LoginForm component passes user inputs via TextInputView’s value props. The values in here are {this.state.email}
and {this.state.email}
. Now it’s about time to explain what state is.
State
“State” is used for data that is going to change. Its role is very similar to properties for a class in OOP. That is why it is only for class components.
The Basic Features of State
- “State” is a JS Object which contains data related to the component
- Updating “state” causes the component to rerender
- “State” must be initialized when the component is created
- “State” can only be updated by
setState()
method
Thanks to its nature, it goes with “props” very well. The main idea of using “state” and “props” together is to store variable data in “state” and pass it to its children via “props”. Let’s take a look at the example below.
// LoginForm component: Class Component
class LoginForm extends Component {
state = { email: '', password: '' };render() {
return (
<View>
<TextInputView
placeholder="sample@gmail.com"
label="Email"
value={this.state.email}
onChangeText={email => this.setState({ email })}
/>
<TextInputView
placeholder="password"
label="Password"
value={this.state.password}
onChangeText={password => this.setState({ password })}
/>
</View>
);
}
}// TextInputView component: Functional Component
const TextInputView = ({ label, value, onChangeText, placeholder}) => {
return (
<View style={containerStyle}>
<Text style={labelStyle}>{label}</Text>
<TextInput
placeholder={placeholder}
style={inputStyle}
value={value}
onChangeText={onChangeText}
/>
</View>
);
};
LoginForm
is the same class component as the last example. TextInputView
is another functional component which is a child of LoginForm
.
TextInputView
takes some props which are used to create views such as label, value etc. As I mentioned, the parent view can pass values via the props. What “LoginForm” passes to TextInputView
are this.state.email
and this.state.password
.
Inside of state
, email
and password
are initialized with an empty string. Where these are actually set values is when onChangeText
is called. TextInput
is a built-in component offered by React Native and it has the onChangeText
event which observes text value changes.
Therefore, the whole passing process looks as below.
- LoginForm:
onChangeText
setstate
values when there are changes to TextInput. - LoginForm:
Get values fromstate
and set it asvalue
props’ values. - TextInputView:
Getlabel
,value
,onChangeText
andplaceholder
via props and display the values in the return statement.
This is everything for this article. If you want to deepen your understanding, I really recommend that you go through the official document from React Native.
References
React Native Official Document — State:
https://facebook.github.io/react-native/docs/state
React Native Official Document — Props:
https://facebook.github.io/react-native/docs/props
React Native Official Document — TextInput:
https://facebook.github.io/react-native/docs/textinput
The Complete React Native and Redux Course — Udemy course from Stephen Grider:
https://www.udemy.com/the-complete-react-native-and-redux-course/learn/v4/content