Open In App

Create a Password Manager using React-Native

Last Updated : 23 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

This article will demonstrate how to create a Password Manager Application using React-Native. To assist users in securely storing and managing their passwords, we will develop a Password Manager mobileĀ­ application using React Native for this project. The application will provide functionalities such as adding, viewing, copying, and deĀ­leting stored passwords.

Let's take a look at how our completed project will look:

Create-a-Password-Manager-using-React-Native

Prerequisites

Steps to Create React Native Application

Step 1: Create a React Native Application

Create a new React Native project for JokesGeneratorApp.

npx create-expo-app PasswordManagerApp

Step 2: ​Change the directory to the project folder:

cd PasswordManagerApp

Project Structure

Package.json

{
"dependencies": {
"react-native-paper": "4.9.2",
"@expo/vector-icons": "^13.0.0",
"react-native-vector-icons/FontAwesome": "*",
"react-native-vector-icons": "10.0.0"
}
}

Approach

This React Native app serves as a password manager. It allows users to add, edit, copy, and delete passwords for various websites. The app maintains a list of passwords, each containing website details, usernames, and masked passwords. Users can copy website names, usernames, and masked passwords to the clipboard for easy access. The app provides an editing feature, initiated by tapping the "Edit" button, enabling users to modify existing passwords.

Example: This example demonstrate a basic password manager where

  • The function "maskPassword" reĀ­ceives a password string as input and returns theĀ­ same password masked with asterisks.
  • This copyText function enableĀ­s users to effortlessly copy teĀ­xt, such as website URLs, usernameĀ­s, and passwords, to their clipboard. Additionally, it sets a temporary aleĀ­rt message called "aleĀ­rtVisible" to notify users that the teĀ­xt has been successfully copieĀ­d.
  • The deĀ­letePassword function allows users to reĀ­move a password entry. It filters theĀ­ passwords array, eliminating the specifieĀ­d password and providing a success message.
  • The eĀ­ditPassword function is invoked when the useĀ­r intends to modify an existing password entry. It activateĀ­s the editing flag, consequeĀ­ntly altering the behavior of theĀ­ "Save Password" button. 
  • The reĀ­nderPasswordList function generateĀ­s a list of password entries based on theĀ­ data in the passwords array. It then maps each password eĀ­ntry to a View, which includes details such as weĀ­bsite, username, and a copy button.
JavaScript
import React, { useState, useEffect } from "react";
import {
    View,
    Text,
    TextInput,
    TouchableOpacity,
    ScrollView,
    StyleSheet,
    Clipboard,
} from "react-native";
import Icon from "react-native-vector-icons/FontAwesome";
import { styles } from "./styles";

const App = () => {
    const [website, setWebsite] = useState("");
    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");
    const [passwords, setPasswords] = useState([]);
    const [alertVisible, setAlertVisible] = useState(false);
    const [editing, setEditing] = useState(false);
    const [editIndex, setEditIndex] = useState(null);

    useEffect(() => {
        showPasswords();
    }, []);

    const maskPassword = (pass) => {
        let str = "";
        for (let index = 0; index < pass.length; index++) {
            str += "*";
        }
        return str;
    };

    const copyText = async (txt) => {
        try {
            await Clipboard.setString(txt);
            setAlertVisible(true);
            setTimeout(() => {
                setAlertVisible(false);
            }, 2000);
        } catch (error) {
            console.error("Error copying text:", error);
        }
    };

    const deletePassword = (website) => {
        const updatedPasswords = passwords.filter(
            (e) => e.website !== website
        );
        setPasswords(updatedPasswords);
        alert(`Successfully deleted ${website}'s password`);
    };

    const showPasswords = () => {
        setPasswords([]);
        setWebsite("");
        setUsername("");
        setPassword("");
        setEditing(false);
        setEditIndex(null);
    };

    const savePassword = () => {
    
        // Check if any of the input fields is empty
        if (!website || !username || !password) {
            alert("Please fill in all fields.");
            return;
        }

        if (editing && editIndex !== null) {
            const updatedPasswords = [...passwords];
            updatedPasswords[editIndex] = {
                website,
                username,
                password,
            };
            setPasswords(updatedPasswords);
            setEditing(false);
            setEditIndex(null);
        } else {
            const newPassword = {
                website,
                username,
                password,
            };
            setPasswords([...passwords, newPassword]);
        }
        setWebsite("");
        setUsername("");
        setPassword("");
    };

    const editPassword = (index) => {
        setEditing(true);
        setEditIndex(index);
        setWebsite(passwords[index].website);
        setUsername(passwords[index].username);
        setPassword(passwords[index].password);
    };

    const renderPasswordList = () => {
        return passwords.map((item, index) => (
            <View style={styles.passwordItem} key={index}>
                <View style={styles.listItem}>
                    <Text style={styles.listLabel}>
                        Website:
                    </Text>
                    <Text style={styles.listValue}>
                        {item.website}
                    </Text>
                    <TouchableOpacity
                        style={styles.copyIcon}
                        onPress={() =>
                            copyText(item.website)
                        }>
                        
                        <Icon
                            name="copy"
                            size={20}
                            color="#555"/>
                            
                    </TouchableOpacity>
                </View>

                <View style={styles.listItem}>
                    <Text style={styles.listLabel}>
                        Username:
                    </Text>
                    <Text style={styles.listValue}>
                        {item.username}
                    </Text>
                    <TouchableOpacity
                        style={styles.copyIcon}
                        onPress={() =>
                            copyText(item.username)
                        }>
                        
                        <Icon
                            name="copy"
                            size={20}
                            color="#555"/>
                            
                    </TouchableOpacity>
                </View>

                <View style={styles.listItem}>
                    <Text style={styles.listLabel}>
                        Password:
                    </Text>
                    <Text style={styles.listValue}>
                        {maskPassword(item.password)}
                    </Text>
                    <TouchableOpacity
                        style={styles.copyIcon}
                        onPress={() =>
                            copyText(item.password)
                        }>
                        
                        <Icon
                            name="copy"
                            size={20}
                            color="#555"/>
                            
                    </TouchableOpacity>
                </View>
                <View style={styles.buttonsContainer}>
                    <TouchableOpacity
                        style={styles.editButton}
                        onPress={() => editPassword(index)}>
                        
                        <Icon
                            name="edit"
                            size={20}
                            color="#fff"/>
                            
                    </TouchableOpacity>
                    <TouchableOpacity
                        style={styles.deleteButton}
                        onPress={() =>
                            deletePassword(item.website)}>
                        
                        <Icon
                            name="trash"
                            size={20}
                            color="white"/>
                            
                    </TouchableOpacity>
                </View>
            </View>
        ));
    };

    return (
        <ScrollView style={styles.container}>
            <View style={styles.content}>
                <Text style={styles.heading}>
                    Password Manager
                </Text>
                <Text style={styles.subHeading}>
                    Your Passwords
                    {alertVisible && (
                        <Text id="alert"> (Copied!)</Text>
                    )}
                </Text>
                {passwords.length === 0 ? (
                    <Text style={styles.noData}>
                        No Data To Show
                    </Text>
                ) : (
                    <ScrollView horizontal>
                        <View style={styles.table}>
                            {renderPasswordList()}
                        </View>
                    </ScrollView>
                )}

                <Text style={styles.subHeading}>
                    {editing
                        ? "Edit Password"
                        : "Add a Password"}
                </Text>
                <TextInput
                    style={styles.input}
                    placeholder="Website"
                    value={website}
                    onChangeText={(text) =>
                        setWebsite(text)
                    }/>
                    
                <TextInput
                    style={styles.input}
                    placeholder="Username"
                    value={username}
                    onChangeText={(text) =>
                        setUsername(text)}/>
                        
                    
                <TextInput
                    style={styles.input}
                    placeholder="Password"
                    secureTextEntry={true}
                    value={password}
                    onChangeText={(text) =>
                        setPassword(text)
                    }/>
                    
                <TouchableOpacity
                    style={styles.submitButton}
                    onPress={savePassword}>
                    
                    <Text style={styles.submitButtonText}>
                        {editing
                            ? "Update Password"
                            : "Add Password"}
                    </Text>
                </TouchableOpacity>
            </View>
        </ScrollView>
    );
};

export default App;
JavaScript
// styles.js

import { StyleSheet } from "react-native";

const styles = StyleSheet.create({
    container: {
        flex: 1,
        margin: 20,
    },
    content: {
        margin: 15,
    },
    heading: {
        fontSize: 30,
        fontWeight: "bold",
        marginBottom: 15,
        textAlign: "center",
        color: "#333",
    },
    subHeading: {
        fontSize: 23,
        fontWeight: "bold",
        marginBottom: 10,
        color: "#333",
    },
    noData: {
        fontSize: 17,
        fontStyle: "italic",
        marginBottom: 20,
        color: "#666",
    },
    table: {
        flexDirection: "row",
        backgroundColor: "white",
        borderRadius: 15,
        elevation: 4,
        marginBottom: 20,
        shadowColor: "grey",
        shadowOffset: { width: 0, height: 0 },
        shadowRadius: 5,
        shadowOpacity: 1,
    },
    passwordItem: {
        flexDirection: "column",
        alignItems: "center",
        borderBottomWidth: 1,
        borderBottomColor: "#ddd",
        padding: 15,
    },
    listItem: {
        flexDirection: "row",
        justifyContent: "space-between",
        alignItems: "center",
        marginRight: 10,
        marginBottom: 10,
    },
    listLabel: {
        fontWeight: "bold",
        marginBottom: 5,
        color: "#333",
        fontSize: 19,
    },
    listValue: {
        flex: 1,
        fontSize: 18,
        color: "#444",
        paddingLeft: 10,
    },
    copyIcon: {
        marginRight: 10,
        paddingLeft: 10,
    },
    deleteButton: {
        backgroundColor: "red",
        borderRadius: 4,
        padding: 5,
        marginLeft: 10,
    },
    editButton: {
        backgroundColor: "blue",
        borderRadius: 4,
        padding: 5,
        marginRight: 10,
    },
    buttonsContainer: {
        flexDirection: "row",
    },
    input: {
        borderWidth: 2,
        borderColor: "#eee",
        paddingVertical: 10,
        paddingHorizontal: 15,
        marginBottom: 20,
        fontSize: 16,
        borderRadius: 10,
        backgroundColor: "white",
        shadowColor: "grey",
        shadowOffset: { width: 0, height: 0 },
        shadowRadius: 10,
        shadowOpacity: 1,
        elevation: 4,
    },
    submitButton: {
        backgroundColor: "green",
        color: "white",
        fontWeight: "bold",
        borderRadius: 10,
        paddingVertical: 15,
        paddingHorizontal: 30,
        shadowColor: "black",
        shadowOffset: { width: 2, height: 2 },
        shadowRadius: 15,
        shadowOpacity: 1,
        elevation: 4,
    },
    submitButtonText: {
        color: "white",
        textAlign: "center",
        fontSize: 18,
    },
});
export { styles };

Steps to Run

To run react native application use the following command:

npx expo start
  • To run on Android:
npx react-native run-android
  • To run on iOS:
npx react-native run-ios

Output:


Next Article

Similar Reads