This tutorial is the sixth part of our React Native Plant App tutorial series. In the , we successfully implemented the Terms of services Modal view and completed the overall UI sections of the Welcome 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. previous part 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 As mentioned in the previous parts, the motivation to work on this tutorial series came from 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 sixth part is also the continuation of coding implementations and designs from the Youtube video tutorial by for 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. React UI Kit Overview In this sixth part of this tutorial series, we are going to implement the Login Screen with different UI sections. The Login screen is going to contain the text fields for email and password along with a button to login as well as the forgot password button. But first, we are going to configure the default Header for all the screens in our navigation file. Then, we will start implementing the different UI sections of the Login Screen. So, let us begin!! Configuring default header in Navigation Here, we are going to configure the default header in the index.js file of folder. We might have remembered that we have defined all the header style configs in the of our navigator. Now, we need to configure those header style options as shown in the code snippet below: './navigation/' defaultNavigationOptions defaultNavigationOptions: { : {}, : &lt;Image source={ ( )} /&gt;, : , : {}, : {}, } headerStyle headerBackImage require '../assets/icons/back.png' headerBackTitle null headerLeftContainerStyle headerRightContainerStyle Here, we have use the component in the option which enables us to set the back button image for each screen. Now in the file, we need to remove the header null configuration in the as shown in the code snippet below: Image headerBackImage Login.js navigationOptions navigationOptions = { } static Hence, we will get the following result in our emulator screen: As we can see, we have got the back button in the header of the Login Screen. Note that this back button will appear in all the screens present in our stack navigator unless custom header is implemented in the Screen file itself. Adding styles Now, we are going to configure some styles which are provided in the code snippet below: defaultNavigationOptions: { : { : theme.sizes.base * , : theme.colors.white, borderBottomColor: , : , }, : &lt;Image source={ ( )} /&gt;, : , : { : , : theme.sizes.base, paddingRight: theme.sizes.base, }, : { : , : theme.sizes.base, }, } headerStyle height 4 backgroundColor // or 'white "transparent" elevation 0 // for android only headerBackImage require '../assets/icons/back.png' headerBackTitle null headerLeftContainerStyle alignItems 'center' marginLeft //for iOS multiply the value by 2 headerRightContainerStyle alignItems 'center' paddingRight Hence, we will get the following result in our emulator screen: As we can see, we have custom the custom-styled header with the back button. Implementing Login Screen In this step, we are going to implement the different UI sections of the Login screen. The Login screen will contain input fields and buttons. The inputs will be of email and password. So, we need to define state variables for inputs as shown in the code snippet below: state = { : ‘’, : ‘‘, } email password Here, we have defined email and password state variables. Adding Email and Password Text Inputs Here, we are going to add email and password text inputs. For that, we need to make the following imports to our screen: Login.js { theme } ; { Button, Block, Text, Input } ; import from '../constants' import from '../components' Here, we have imported the theme from folder and Input component from our predefined custom components. Now, we are going to make use of the component in the function of the file in order to add text inputs to the screen. For that, we need to make use of the code from the following code snippet: './constants.' Input render() Login.js render(){ ( <Text h1 bold>Login</Text> <Block middle> <Input label="Email" style = {styles.input} defaultValue={this.state.email} onChangeText={text => this.setState({email : text})} /> <Input secure label="Password" style = {styles.input} defaultValue={this.state.password} onChangeText={text => this.setState({password : text})} /> </Block> </Block> ); } return < = * ]}> Block padding {[0, theme.sizes.base 2 Here, we have a component wrapping component and Input components. The Input components are configured with , and props. Then, we are taking the input value and changing our state variables by using the event. There are some styles configured to components as well which is provided in the code snippet below: Block Text label style defaultValue onChangeText Input input: { : , : , : theme.colors.gray2, : StyleSheet.hairlineWidth, }, borderRadius 0 borderWidth 0 borderBottomColor borderBottomWidth Now, we are going to add valid email and password values. For that, we need to define two constants as shown in the code snippet below: VALID_EMAIL = ; VALID_PASSWORD = ; const "kriss @kriss.com" const "12345" Now, we need to set these valid email and password constants to the email and password states as shown in the code snippet below: state = { : VALID_EMAIL, : VALID_PASSWORD, } email password Hence, we will get the following result in our emulator screen: As we can see, we have got the inputs as well as valid input values in the Login Screen. But we can see that the keyboard blocks the inputs when we trigger the keyboard to appear on the screen. So, we need to avoid the keyboard from blocking the inputs. Avoiding Keyboard In order to avoid the keyboard from blocking the inputs or any other view elements, we need to make use of the component from the package. But first, we need to import this component into our screen: KeyboardAvoidingView react-native Login.js { StyleSheet, KeyboardAvoidingView } ; import from 'react-native' Now, we need to wrap the overall screen template in the function of Login screen with component as shown in the code snippet below: render() KeyboardAvoidingView ( <Block padding={[0, theme.sizes.base * 2]}> <Text h1 bold>Login</Text> <Block middle> <Input label="Email" style = {styles.input} defaultValue={this.state.email} onChangeText={text => this.setState({email : text})} /> <Input secure label="Password" style = {styles.input} defaultValue={this.state.password} onChangeText={text => this.setState({password : text})} /> </Block> </Block> </KeyboardAvoidingView> ); return < = = > KeyboardAvoidingView style {styles.login} behavior "padding" Here, we have also added some style configurations and behavior props to the component. the behavior prop is set to padding in order to show padding when the keyboard appears. The required style is provided in the code snippet below: KeyboardAvoidingView : { : , justifyContent: , }, login flex 1 'center' Hence, we will get the following result in our emulator screen: As we can see, our input fields are shifted upwards when the keyboard appears to avoid its blocking. Adding Buttons In this step, we are going to add buttons to the Login screen. We are going to add two buttons. One is the Login button and another is Forgot password 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: handleLogin() { { navigation } = .props; { email, password } = .state; errors = []; .setState({ : }); (email !== VALID_EMAIL) { errors.push( ); } (password !== VALID_PASSWORD) { errors.push( ); } .setState({ errors, : }); (!errors.length) { navigation.navigate( ); } } const this const this const this loading true // check with backend API or with some static data if 'email' if 'password' this loading false if "Browse" Here, we have used the component. The component with some style props wraps the component in order to display text inside the button. Hence, we will get the following result in our emulator screen: Button Button Text As we can see, we have got the Login button with gradient style and Forgot password button in plain underlined text. Configuring the Login button As we might have seen that, we have called the function in the event of the Login button. But, we still have not defined any sort of function named . Here, we are going to defined and configure the function. But first, we need to define some extra states for errors and loading effects: handleLogin() onPress handleLogin() handleLogin() state = { : VALID_EMAIL, : VALID_PASSWORD, : [], : , } email password errors loading false Here, we have defined errors state as array and loading state as false. The errors state will store the errors while logging in. The loading state will trigger some sort of button style to display logging in loader. Now, in the function, we need to configure the valid login and invalid login with errors. For that, we need to use the code from the following code snippet: handleLogin() handleLogin() { { navigation } = .props; { email, password } = .state; errors = []; .setState({ : }); (email !== VALID_EMAIL) { errors.push( ); } (password !== VALID_PASSWORD) { errors.push( ); } .setState({ errors, : }); (!errors.length) { navigation.navigate( ); } } const this const this const this loading true // check with backend API or with some static data if 'email' if 'password' this loading false if "Browse" Here, we have imported the navigation prop as well as the states. When we press the Login button and call the function, the loading state is set to true to display the loading. Then, the email and password states are checked by comparing them to valid values. If the values are wrong then errors are pushed to errors array state. If the email and password are valid then the loading state is set to false and then navigated to Browse screen. handleLogin() Handling errors Now, we need to show some sort of message or style change when the wrong email or password is entered. First, we need to import the state variables in the function as shown in the code snippet below: render() render(){ { navigation } = .props; { loading, errors } = .state; hasErrors = key =&gt; errors.includes(key) ? styles.hasErrors : ; const this const this const null Here, we have imported the loading and errors states. Then, we have defined a new function called 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 particular input field in order to show the error. For that, we need to use code from the following code snippet: hasErrors() ( <Block padding={[0, theme.sizes.base * 2]}> <Text h1 bold>Login</Text> <Block middle> <Input label="Email" error={hasErrors('email')} style={[styles.input, hasErrors('email')]} defaultValue={this.state.email} onChangeText={text => this.setState({ email: text })} /> <Input secure label="Password" error={hasErrors('password')} style={[styles.input, hasErrors('password')]} defaultValue={this.state.password} onChangeText={text => this.setState({ password: text })} /> <Button gradient onPress={() => this.handleLogin()}> <Text bold white center>Login</Text> </Button> <Button onPress={() => {}}> <Text gray caption center style={{ textDecorationLine: 'underline' }}> Forgot your password? </Text> </Button> </Block> </Block> </KeyboardAvoidingView> ); return < = = > KeyboardAvoidingView style {styles.login} behavior "padding" Here, we have added the error prop to both the Input components which call the function with specific parameters. Then, we have also added the error style which is provided1 in the code snippet below: hasError() hasErrors: { : theme.colors.accent, } borderBottomColor Hence, we will get the following result in the emulator screen: As we can see, the color of the input fields turns red when we enter the wrong credentials. Note that, the screen does not navigate to Browse Screen because we have commented it out in the index.js file of the navigation folder. Loading state configuration Here, we are going to show the loader in the Login button when we click on the Login button. For that, we need to import the as shown in the code snippet below: ActivityIndicator { ActivityIndicator, Keyboard, KeyboardAvoidingView, StyleSheet } import from 'react-native' Now, we need to close the keyboard whenever we press the login button. For that, we need to use the function of the component as shown in the code snippet below: dismiss() Keyboard handleLogin() { { navigation } = .props; { email, password } = .state; errors = []; Keyboard.dismiss(); const this const this const Now, we need to display the or component on the basis of the state in the Login button. For that, we need to use the following code inside the component for login button: ActivityIndicator Text loading Button <Button gradient onPress={() => .handleLogin()}> {loading ? <Text bold white center>Login</Text> this : < = = /> ActivityIndicator size "small" color "white" } </ > Button Now, in order to render the loader, we need to add delay to function. For that, we are going to use function in our function as shown in the code snippet below: handleLogin() setTimeout handleLogin() handleLogin() { { navigation } = .props; { email, password } = .state; errors = []; Keyboard.dismiss(); .setState({ : }); setTimeout(() =&gt; { (email !== VALID_EMAIL) { errors.push( ); } (password !== VALID_PASSWORD) { errors.push( ); } .setState({ errors, : }); (!errors.length) { navigation.navigate( ); } }, ); } const this const this const this loading true // check with backend API or with some static data if 'email' if 'password' this loading false if "Browse" 2000 Here, we have used the function and delayed the outcome of pressing the Login button by 2 seconds. Hence, we will get the following result in our emulator screen: As we can see, a loader appears whenever we press the Login button. setTimeout With this, we have come to the end of this part of the tutorial. However, we can remove the setTimeout function as it is used only to display the loading state. In the real scenario, when we are requesting some data from the server, it will automatically show up. Finally, we have successfully completed the implementation of the Login Screen in our React Native Plant UI App. Conclusion This tutorial is the sixth part of the React Native Plant App UI tutorial series. In this part, we continued from where we left off in the fifth part of this tutorial series. In this part of the tutorial, we learned how to config a navigation file to set the default header with a custom back button. Then, we got stepwise guidance on how to use different custom components to implement the overall UI of the Login screen. Lastly, we also learned how to show the loader as well as handle the errors. In the next part of this tutorial series, we are going to implement the overall UI of the Forgot Password screen in the file. Forgot.js