Open In App

Create a Phonebook and Call App using React-Native

Last Updated : 25 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

React-Native is an open-source framework used to develop cross-platform applications i.e., you can write code in React-Native and publish it as an Android or IOS app. In this article, we will build a basic Phonebook and call app using React-Native. The phonebook app will show all the contacts from the contact book. When you click any of the contacts, it will ask you to call that number. You can also search for a contact using the search bar.

Preview of final output: Let us have a look at how the final application will look like.

CallingApp

Phonebook App

Prerequisites:

Approach to create Phonebook and Call App:

The app screen will display the contacts list in sorted order. For illustration, I have created some dummy contacts. To call any number, you need to click on that contact. Also, you can use search bar to search the required contact. To fetch the contacts, we use expo-contacts package. To get permission for contacts, we use requestPermissionsAsync() function provided by expo-contacts package. Thus the app provides basic functionality for calling a number from your phonebook.

Steps to Create React-Native App:

Step 1: Create a React Native app by using this command:

npx create-expo-app CallingApp

Step 2: Navigate to our project through this command:

cd CallingApp

Step 3: Install the required dependencies using the following command

npm install @react-navigation/native @react-navigation/stack expo-contacts

Project Structure:

Calling-Structure

Project Structure

The updated dependencies in package.json file will look like:

"dependencies": {
    "expo-status-bar": "~1.6.0",
    "react-native-contacts": "^7.0.8",
    "react-native-permissions": "^4.0.0",
    "expo-permissions": "~14.2.1",
    "expo-contacts": "~12.2.0",
    "@react-navigation/native": "6.0.0",
    "@react-navigation/stack": "^6.3.20",
    "react-native-gesture-handler": "~2.12.0",
    "react-native-safe-area-context": "4.6.3",
    "react-native-screens": "~3.22.0"
}

Example: Write the code in respective files

  • App.js: This file imports all the necessary components and renders them
  • ContactsScreen.js: This file defines how the components will be displayed on screen
  • ContactsFunctions.js: This file contains the dummy data to display on the screen.

Javascript




// App.js
import React from 'react';
import { NavigationContainer }
    from '@react-navigation/native';
import { createStackNavigator }
    from '@react-navigation/stack';
import ContactsScreen
    from './ContactsScreen';
 
const Stack = createStackNavigator();
 
const App = () => {
    return (
        <NavigationContainer>
            <Stack.Navigator
                initialRouteName="ContactsScreen">
                <Stack.Screen
                    name="ContactsScreen"
                    component={ContactsScreen} />
            </Stack.Navigator>
        </NavigationContainer>
    );
};
 
export default App;


Javascript




// ContactsScreen.js
import React, { useEffect, useState } from 'react';
import {
    View, Text, FlatList,
    TouchableOpacity, TextInput,
    Pressable
} from 'react-native';
import {
    requestContactsPermission,
    makeCall, filterContacts
} from './ContactsFunctions';
 
const ContactsScreen = () => {
    const [contacts, setContacts] = useState([]);
    const [filteredContacts, setFilteredContacts] = useState([]);
    const [searchQuery, setSearchQuery] = useState('');
 
    useEffect(() => {
        requestContactsPermission(setContacts, setFilteredContacts);
    }, []);
 
    const handleSearch = () => {
        filterContacts(contacts, searchQuery, setFilteredContacts);
    };
 
    const renderItem = ({ item }) => (
        <TouchableOpacity
            onPress={() => makeCall(item)}
            style={{ borderBottomWidth: 1, borderColor: '#228B22' }}
        >
            <View
                style={{
                    padding: 20,
                    backgroundColor: 'white',
                }}
            >
                <Text style=
                    {
                        { color: '#228B22' }}>
                    {item.name}: {item.phoneNumbers
                        && item.phoneNumbers.length > 0 &&
                        item.phoneNumbers[0].number}
                </Text>
            </View>
        </TouchableOpacity>
    );
 
    return (
        <View>
            <View style=
                {
                    {
                        flexDirection: 'row',
                        alignItems: 'center',
                        margin: 10
                    }
                }>
                <TextInput
                    style=
                    {
                        {
                            flex: 1, height: 40,
                            borderColor: '#228B22',
                            borderWidth: 1, marginRight: 10,
                            paddingLeft: 10, color: '#228B22'
                        }
                    }
                    placeholder="Search"
                    value={searchQuery}
                    onChangeText={
                        (text) =>
                            setSearchQuery(text)
                    }
                />
                <Pressable
                    style={({ pressed }) => [
                        {
                            backgroundColor: pressed ? '#1e8449' : '#2ecc71',
                            padding: 10,
                            borderRadius: 5,
                        },
                    ]}
                    onPress={handleSearch}
                >
                    <Text style=
                        {
                            {
                                color: 'white'
                            }
                        }>
                        Search
                    </Text>
                </Pressable>
            </View>
            <FlatList
                data={filteredContacts}
                renderItem={renderItem}
                keyExtractor={(item) => item.id}
            />
        </View>
    );
};
 
export default ContactsScreen;


Javascript




// ContactsFunctions.js
import * as Contacts from 'expo-contacts';
import { Linking, Alert } from 'react-native';
 
// Add dummy contacts for testing
const dummyContacts = [
    {
        id: '1',
        name: 'Geek 1',
        phoneNumbers: [
            {
                number: '123-456-7890',
            },
        ],
    },
    {
        id: '2',
        name: 'Geek 2',
        phoneNumbers: [
            {
                number: '987-654-3210',
            },
        ],
    },
    {
        id: '3',
        name: 'Geek 3',
        phoneNumbers: [
 
        ],
    },
    // Add more dummy contacts as needed
];
 
export const requestContactsPermission =
    async (setContacts, setFilteredContacts) => {
        try {
            const { status } =
                await Contacts.requestPermissionsAsync();
            // Comment below two lines after testing the contacts
            setContacts(dummyContacts);
            setFilteredContacts(dummyContacts);
 
            if (status === 'granted') {
                setContacts(sortedContacts);
                setFilteredContacts(sortedContacts);
 
            } else {
 
                console.log('Contacts permission denied');
            }
        } catch (error) {
            console
                .error('Error requesting contacts permission:', error);
        }
    };
 
export const fetchContacts =
    async (setContacts, setFilteredContacts) => {
        try {
            // Use dummyContacts for testing
            setContacts(dummyContacts);
            setFilteredContacts(dummyContacts);
        } catch (error) {
            console.error('Error fetching contacts:', error);
        }
    };
 
export const makeCall = (contact) => {
    const phoneNumber =
        contact.phoneNumbers
            &&
            contact.phoneNumbers.length > 0
            ? contact.phoneNumbers[0].number
            : null;
 
    if (phoneNumber) {
        const url = `tel:${phoneNumber}`;
        Linking.openURL(url);
    } else {
        Alert.alert('No phone number available for this contact.');
    }
};
 
export const filterContacts =
    (contacts, searchQuery, setFilteredContacts) => {
        const filtered = contacts.filter(
            (contact) =>
                contact.name.toLowerCase()
                    .includes(searchQuery.toLowerCase()) ||
                (contact.phoneNumbers &&
                    contact.phoneNumbers.length > 0 &&
                    contact.phoneNumbers[0].number.includes(searchQuery))
        );
 
        setFilteredContacts(filtered);
    };


You can use any of the below two methods to run the app

Method 1: Open the terminal and enter the following command to run the app

npx expo start

Method 2: You can use emulator or connect computer to your device using USB and run the below command

  • To run on Android:
npx react-native run-android
  • To run on Ios:
npx react-native run-ios

Output:

CallingApp

Calling App



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads