Create a custom hook to Show/Hide Password Visibility in React Native

Dec 11, 2021

5 min read

#expo

Building login and signup forms in a React Native app comprise input fields and buttons. One field that you will often find yourself adding to these forms is the password field. This password field is composed of using React Native's TextInput component.

The common behavior of this field is to hide a user's password behind obscure characters.

Take a look at an example of the TextInput component that is used to create a password field.

JavaScript icon

1import React, { useState } from 'react';
2import { StyleSheet, TextInput, View } from 'react-native';
3
4export default function App() {
5 const [password, setPassword] = useState('');
6
7 return (
8 <View style={styles.container}>
9 <View style={styles.inputContainer}>
10 <TextInput
11 style={styles.inputField}
12 name='password'
13 placeholder='Enter password'
14 autoCapitalize='none'
15 autoCorrect={false}
16 textContentType='newPassword'
17 secureTextEntry
18 value={password}
19 enablesReturnKeyAutomatically
20 onChangeText={text => setPassword(text)}
21 />
22 </View>
23 </View>
24 );
25}
26
27const styles = StyleSheet.create({
28 container: {
29 flex: 1,
30 backgroundColor: '#F5EEDC',
31 alignItems: 'center',
32 justifyContent: 'center',
33 paddingHorizontal: 12
34 },
35 inputContainer: {
36 backgroundColor: 'white',
37 width: '100%',
38 borderRadius: 8,
39 flexDirection: 'row',
40 alignItems: 'center',
41 borderWidth: 4,
42 borderColor: '#d7d7d7'
43 },
44 inputField: {
45 padding: 14,
46 fontSize: 22,
47 width: '90%'
48 }
49 }
50});

It uses the secureTextEntry prop such that when a text value is entered in the input field, it is unclear what is being entered in that field.

Here is the output of the above snippet on a device:

ss1

However, giving an option to a user to let them see the current value they enter could lead to a good experience and might be necessary in some cases.

Show or Hide Password Visibility Hook

🔗

To add the ability to show or hide the password field's visibility, let's create a custom hook in a new file called useTogglePasswordVisibility.js.

Start by importing the useState hook from React library. You will need to create two different state variables to toggle between the field's visibility and change the icon.

Then define a function called useTogglePasswordVisibility. Inside this function, create two new state variables. The first one is called passwordVisibility. Its initial value is set to boolean true. The reason is that this variable will be the value of the prop secureTextEntry on the TextInput component. You would want to hide the password field initially when the user enters the password in the input field.

The second state variable defined is called rightIcon. It has a default value of eye. This value depends on the Icon Library you're using in your React Native app. For this example, I'm using MaterialCommunityIcons from Expo Vector Icons.

JavaScript icon

1export const useTogglePasswordVisibility = () => {
2 const [passwordVisibility, setPasswordVisibility] = useState(true);
3 const [rightIcon, setRightIcon] = useState('eye');
4
5 // ...
6};

Next, add a method called handlePasswordVisibility that will allow the app user to toggle the password field's visibility between shown and hidden state.

Lastly, do not forget to return all the variables and the handler method.

JavaScript icon

1export const useTogglePasswordVisibility = () => {
2 const [passwordVisibility, setPasswordVisibility] = useState(true);
3 const [rightIcon, setRightIcon] = useState('eye');
4
5 const handlePasswordVisibility = () => {
6 if (rightIcon === 'eye') {
7 setRightIcon('eye-off');
8 setPasswordVisibility(!passwordVisibility);
9 } else if (rightIcon === 'eye-off') {
10 setRightIcon('eye');
11 setPasswordVisibility(!passwordVisibility);
12 }
13 };
14
15 return {
16 passwordVisibility,
17 rightIcon,
18 handlePasswordVisibility
19 };
20};

Use the Password Visibility Hook

🔗

Start by updating import statements in the App.js file:

JavaScript icon

1import React, { useState } from 'react';
2import { StyleSheet, Pressable, TextInput, View } from 'react-native';
3import { MaterialCommunityIcons } from '@expo/vector-icons';
4
5import { useTogglePasswordVisibility } from './hooks/useTogglePasswordVisibility';

Next, access the required variables and method from the useTogglePasswordVisibility hook. Add the following line at the top of the App component:

JavaScript icon

1export default function App() {
2 const { passwordVisibility, rightIcon, handlePasswordVisibility } =
3 useTogglePasswordVisibility();
4 const [password, setPassword] = useState('');
5
6 // ...
7}

Modify the TextInput component's prop. Make sure to add the passwordVisibility as the value to the secureTextEntry prop.

JavaScript icon

1<TextInput
2 secureTextEntry={passwordVisibility}
3 // ... rest of the props remain unchanged
4/>

Inside the View component that wraps the TextInput, add a button using the Pressable component. This button will allow the user to toggle between the hidden and shown state of the password field.

This button wraps the icon component.

JavaScript icon

1<View style={styles.inputContainer}>
2 {/* After TextInput component */}
3 <Pressable onPress={handlePasswordVisibility}>
4 <MaterialCommunityIcons name={rightIcon} size={22} color="#232323" />
5 </Pressable>
6</View>

That's all! Here is the output after this step:

ss2

Here is the complete code for the App.js file:

JavaScript icon

1import React, { useState } from 'react';
2import { StyleSheet, Pressable, TextInput, View } from 'react-native';
3import { MaterialCommunityIcons } from '@expo/vector-icons';
4
5import { useTogglePasswordVisibility } from './hooks/useTogglePasswordVisibility';
6
7export default function App() {
8 const { passwordVisibility, rightIcon, handlePasswordVisibility } =
9 useTogglePasswordVisibility();
10 const [password, setPassword] = useState('');
11
12 return (
13 <View style={styles.container}>
14 <View style={styles.inputContainer}>
15 <TextInput
16 style={styles.inputField}
17 name="password"
18 placeholder="Enter password"
19 autoCapitalize="none"
20 autoCorrect={false}
21 textContentType="newPassword"
22 secureTextEntry={passwordVisibility}
23 value={password}
24 enablesReturnKeyAutomatically
25 onChangeText={text => setPassword(text)}
26 />
27 <Pressable onPress={handlePasswordVisibility}>
28 <MaterialCommunityIcons name={rightIcon} size={22} color="#232323" />
29 </Pressable>
30 </View>
31 </View>
32 );
33}
34
35const styles = StyleSheet.create({
36 container: {
37 flex: 1,
38 backgroundColor: '#F5EEDC',
39 alignItems: 'center',
40 justifyContent: 'center',
41 paddingHorizontal: 12
42 },
43 inputContainer: {
44 backgroundColor: 'white',
45 width: '100%',
46 borderRadius: 8,
47 flexDirection: 'row',
48 alignItems: 'center',
49 borderWidth: 4,
50 borderColor: '#d7d7d7'
51 },
52 inputField: {
53 padding: 14,
54 fontSize: 22,
55 width: '90%'
56 }
57});

Source code at this GitHub repo


Enjoyed this post? Sign up to my newsletter!

A periodic update about my recent blog posts and tutorials. Join 1300+ devs!

No spam, unsubscribe at any time!

Subscribe on Revue

HomeBlogNewsletterAbout meSpeakingEmail

©  2019-2022 Aman Mittal · All Rights Reserved