This tutorial is the eighth part of our React Native Plant App tutorial series. In the previous part, we successfully implemented the different UI sections of the Forgot Password Screen. This tutorial is the continuation of the same tutorial from where we left off in the last part. So, it is recommended to go through the previous part in order to get insight and knowledge of the overall project.
In case of wanting to learn from the beginning, all the previous parts for this tutorial series are available below:
- React Native Plant App UI #1: Getting Started
- React Native Plant App UI #2: Implementing Custom Components
- Building React Native Plant App UI #3: Implementing Welcome Screen
- React Native Plant App UI #4: Illustration Slider and Animated Steps
- React Native Plant App UI #5: Terms of Service Modal
- Building React Native Plant App UI #6: Login Screen
- React Native Plant App UI #7: Forgot Password Screen
As stated in the previous parts, the tutorial series was inspired by the React Native App Templates that provide a wide variety of mobile application templates written in React Native and powered by universal features and design. These app templates allow us to implement our own apps and even start our own startups. And, this eighth part is also the continuation of coding implementations and designs from the Youtube video tutorial by React UI Kitfor the Plant App. The video tutorial delivers the coding implementation of the overall app very thoroughly. However, there is no verbal guidance for coding and implementation. Hence, this tutorial series is the implementation of the same coding style and designs in the form of the article. Thus, the learners can go through each step and take their time understanding the implementations.
Overview
In this eighth part of this tutorial series, we are going to implement the Sign-Up Screen with different UI sections. The Sign-Up screen will be more or less similar to the Login Screen or Forgot Password as well. The UI sections are very much similar to that of the Login Screen. This screen will contain comparatively more input fields which is the only difference in terms of UI of different screens. We will also implement the error handling as well as the loading state at the end.
So, let us begin!!
Implementing Sign-Up Screen
We have already set up the simple React Native template in the Signup.js screen file. And, we have also set up the navigation configuration from the Login screen to the Sign-Up screen. Here, we are going to implement the different UI sections of the Sign-Up Screen. This screen is more or less similar to Login Screen. So, we are going to copy some of the codes from our Login screen to the Sign-Up screen. First, we are going to import the necessary components as shown in the code snippet below:
import { Alert, ActivityIndicator, Keyboard, KeyboardAvoidingView, StyleSheet } from 'react-native';
import { Button, Block, Input, Text } from '../components';
import { theme } from '../constants';
Here, we have imported the required components to build this screen from the react-native package. Then, we have also imported with the predefined custom components from our ‘./components/’ folder. The theme module is also imported from the ‘./constants/’. Now, we are going to define and initialize the required state variables as shown in the code snippet below:
state = {
email: null,
username: null,
password: null,
errors: [],
loading: false,
}
Here, we have defined the email
, username
, password
state variables and is set to the null
value, errors
array and loading
state as false.
Adding Header and Input Section
Note that we need to remember to remove the navigationOptions
config as well. Here, we are going to add the header section as well as the input field. This screen will contain three input fields for entering the email, username, and password. The styles of the input field will be similar to that in the Login screen. Now, in order to implement these sections, we need to make use of the code from the following code snippet in the render()
function of Signup.js file:
render(){
return (
<KeyboardAvoidingView style={styles.signup} behavior="padding">
<Block padding={[0, theme.sizes.base * 2]}>
<Text h1 bold>Sign Up</Text>
<Block middle>
<Input
email
label="Email"
style={[styles.input]}
defaultValue={this.state.email}
onChangeText={text => this.setState({ email: text })}
/>
<Input
label="Username"
style={[styles.input]}
defaultValue={this.state.username}
onChangeText={text => this.setState({ username: text })}
/>
<Input
secure
label="Password"
style={[styles.input]}
defaultValue={this.state.password}
onChangeText={text => this.setState({ password: text })}
/>
</Block>
</Block>
</KeyboardAvoidingView>
);
}
Here, we have used the KeyboardAvoidingView
as the parent component. This component helps to shift the content inside it shift above the keyboard when the actual keyboard is triggered in the app. Then, we have the Block
component wrapping the Text
component and another child Block
component. The child Block
component wraps the Input
component for our email, username, and password entries. The Input
component has some props from the label
and defaultValue
. We receive the value of email, username, and password by changing the there state values in the onChangeText
event. There are some styles configured to the components as well which is provided in the code snippet below:
signup: {
flex: 1,
justifyContent: 'center',
},
input: {
borderRadius: 0,
borderWidth: 0,
borderBottomColor: theme.colors.gray2,
borderBottomWidth: StyleSheet.hairlineWidth,
},
hasErrors: {
borderBottomColor: theme.colors.accent,
}
Hence, we will get the following result in our emulator screen:As we can see, we have got the Header as well as the input fields in our Sign-Up screen. And, when the keyboard is triggered by tapping on any input fields, all the Input
components are shifted up to avoid blockage from the inputs from the keyboard.
Adding Buttons
In this step, we are going to add buttons to the Sign-Up screen. We are going to add two buttons. One is the Sign-Up button and another is navigation back to the Login Screen button. This button will be placed below the input fields. In order to add buttons, we need to use the code from the following code snippet:
<Block middle>
<Input
email
label="Email"
style={[styles.input]}
defaultValue={this.state.email}
onChangeText={text => this.setState({ email: text })}
/>
<Input
label="Username"
style={[styles.input]}
defaultValue={this.state.username}
onChangeText={text => this.setState({ username: text })}
/>
<Input
secure
label="Password"
style={[styles.input]}
defaultValue={this.state.password}
onChangeText={text => this.setState({ password: text })}
/>
<Button gradient onPress={() => this.handleSignUp()}>
{loading ?
<ActivityIndicator size="small" color="white" /> :
<Text bold white center>Sign Up</Text>
}
</Button>
<Button onPress={() => navigation.navigate('Welcome ')}>
<Text gray caption center style={{ textDecorationLine: 'underline' }}>
Back to Login
</Text>
</Button>
</Block>
Here, we have used the Button
component. The Button
component with some style props wraps the Text
component in order to display text inside the button. The Back to Login button has the navigation configured to its onPress
event. Hence, we will get the following result in our emulator screen:As we can see, we have the required buttons on the Sign-Up screen. Taping on the Back to Login button enables us to navigate back to the Login screen.
Configuring the Sign-Up button
As we might have seen that, we have called the handleSignUp()
function in the onPress
event of the Sign-Up button. But, we still have not defined any sort of function named handleSignUp()
. Here, we are going to defined and configure the handleSignUp()
function. Now, in the handleSignUp()
function, we need to check the email, username, and password for errors. We are also going to configure the loading
state by changing the states of the loading
state before and after the successful signing up. For that, we need to use the code from the following code snippet:
handleSignUp() {
const { navigation } = this.props;
const { email, username, password } = this.state;
const errors = [];
Keyboard.dismiss();
this.setState({ loading: true });
// check with backend API or with some static data
if (!email) errors.push('email');
if (!username) errors.push('username');
if (!password) errors.push('password');
this.setState({ errors, loading: false });
if (!errors.length) {
Alert.alert(
'Success!',
'Your account has been created',
[
{
text: 'Continue', onPress: () => {
navigation.navigate('Browse')
}
}
],
{ cancelable: false }
)
}
}
Here, we have also used the dismiss()
function of the Keyboard
component in order to hide the keyboard when we press the Sign-Up button. Then, on the basis of the value of the email
, username
and password
, we have pushed the errors in the errors
array. Then, on the basis of the length of errors
array we have shown in the sign-up success alert.
Handling errors
Now, we need to show some sort of style change when the wrong email is entered. First, we need to import the state variables in the render()
function as shown in the code snippet below:
render() {
const { navigation } = this.props;
const { loading, errors } = this.state;
const hasErrors = key => errors.includes(key) ? styles.hasErrors : null;
Here, we have imported the loading
and errors
states. Then, we have defined a new function called hasErrors()
and it returns the value depending on the key value of the errors
state array. Now, we are going to change the style of the input field in order to show the error. For that, we need to use code from the following code snippet:
<Input
email
label="Email"
error={hasErrors('email')}
style={[styles.input, hasErrors('email')]}
defaultValue={this.state.email}
onChangeText={text => this.setState({ email: text })}
/>
<Input
label="Username"
error={hasErrors('username')}
style={[styles.input, hasErrors('username')]}
defaultValue={this.state.username}
onChangeText={text => this.setState({ username: text })}
/>
<Input
secure
label="Password"
error={hasErrors('password')}
style={[styles.input, hasErrors('password')]}
defaultValue={this.state.password}
onChangeText={text => this.setState({ password: text })}
/>
Here, we have added the error
prop to the Input
components which call the hasError()
function with specific parameters Then, we have also added the error style which is provided in the code snippet below:
hasErrors: {
borderBottomColor: theme.colors.accent,
}
Hence, we will get the following result in the emulator screen:As we can see, when we enter all the inputs correctly, the sign-up success alert is shown on the screen.
And when we tap the ‘Continue’ button on the alert message, we should navigate to the Browse screen. But, navigation to Browse screen does not work because we have not removed the comment from the Browse screen in the index.js file of the ‘./navigation/’ folder. And we have not implemented it as well.
Now, we need to test the errors which are shown in the emulator simulation below:
As we can see, if we do not enter any of the input, we get the error style in the respective input field.
We can set the setTimeout
function in order to display the loading state just as in the Login screen. In the real scenario, when we are requesting some data from the server, it will automatically show up. With this, we have come to the end of this part of the tutorial.
Finally, we have successfully completed the implementation of the Sign-Up Screen in our React Native Plant UI App.
Conclusion
This tutorial is the eighth part of the React Native Plant App UI tutorial series. In this part, we continued from where we left off in the seventh part of this tutorial series. In this part of the tutorial, we got stepwise guidance on how to use different custom components to implement the overall UI of the Sign-Up screen. This Screen implementation is similar to that of the Login Screen from our previous tutorial part. Lastly, we also learned how to handle the errors and show the success alert messages.
In the next part of this tutorial series, we are going to start implementing different UI sections of our Browse screen.