Working with Contacts (expo-contacts)
1. Requesting Contacts Permissions
| Permission | Platform Support | Description |
|---|---|---|
| contacts | iOS, Android | Allows access to the user's contacts list and details. |
Example: Requesting Contacts Permission
import * as Permissions from 'expo-permissions';
import { Contacts } from 'expo-contacts';
const requestContactsPermission = async () => {
const { status } = await Permissions.askAsync(Permissions.CONTACTS);
if (status === 'granted') {
console.log('Permission granted!');
} else {
console.log('Permission denied.');
}
};
requestContactsPermission();
Note: On iOS, the app must also include the
NSContactsUsageDescription key in its Info.plist to explain why it needs access to contacts.
Warning: On Android, the
READ_CONTACTS and WRITE_CONTACTS permissions are required for full contact access. These must be declared in app.json.
2. Getting All Contacts
| Property | Description | Values |
|---|---|---|
| getContactsAsync() | Retrieves all contacts from the device's contact list | Promise<Contact[]> |
Example: Fetching All Contacts
import * as Contacts from 'expo-contacts';
const getContacts = async () => {
const { data } = await Contacts.getContactsAsync();
console.log(data);
};
getContacts();
Note: Requires appropriate permissions to access contacts.
3. Getting Contact by ID
| Property | Description | Values |
|---|---|---|
| id | Unique identifier for the contact | string |
Example: Fetching a Contact by ID
import * as Contacts from 'expo-contacts';
const getContactById = async (contactId) => {
try {
const contact = await Contacts.getContactByIdAsync(contactId);
console.log('Contact found:', contact);
} catch (error) {
console.error('Error fetching contact:', error);
}
};
// Usage
getContactById('contact-id-here');
4. Creating Contacts
| Property | Description | Example |
|---|---|---|
| name | Contact's full name | "John Doe" |
| phoneNumbers | Array of phone numbers | [{ number: "+1234567890" }] |
| emailAddresses | Array of email addresses | [{ address: "john@example.com" }] |
| addresses | Array of address objects | [{ street: "123 Main St" }] |
Example: Creating a Contact
import * as Contacts from 'expo-contacts';
const contact = {
name: 'Jane Smith',
phoneNumbers: [{ number: '+1987654321' }],
emailAddresses: [{ address: 'jane@example.com' }],
addresses: [{ street: '456 Oak Ave' }]
};
const { data } = await Contacts.createContactAsync(contact);
console.log('Created contact with ID:', data.id);
Note: The
createContactAsync method returns a promise that resolves to an object containing the created contact's ID and other metadata.
5. Updating Contacts
| Property | Description | Values |
|---|---|---|
| id | Unique identifier for the contact | string |
| name | Contact's name | string |
| phoneNumbers | List of phone numbers associated with the contact | Array<{label: string, number: string}> |
| emailAddresses | List of email addresses associated with the contact | Array<{label: string, email: string}> |
| addresses | List of addresses associated with the contact | Array<{label: string, street: string, city: string, region: string, postCode: string, country: string}> |
| urls | List of URLs associated with the contact | Array<{label: string, url: string}> |
| note | Additional notes about the contact | string |
Example: Updating a Contact's Phone Number
import * as Contacts from 'expo-contacts';
const contactId = 'contact-id-here';
const updatedContact = {
id: contactId,
name: 'John Doe',
phoneNumbers: [
{
label: 'mobile',
number: '+1 (555) 123-4567'
}
]
};
await Contacts.updateContactAsync(contactId, updatedContact);
Example: Adding an Email Address to a Contact
import * as Contacts from 'expo-contacts';
const contactId = 'contact-id-here';
const updatedContact = {
id: contactId,
emailAddresses: [
{
label: 'work',
email: 'john.doe@company.com'
}
]
};
await Contacts.updateContactAsync(contactId, updatedContact);
6. Deleting Contacts
| Method | Description | Notes |
|---|---|---|
| deleteContactAsync(contactId) | Deletes a contact by its unique ID | Returns a Promise that resolves when deletion is complete |
Example: Deleting a Contact
import { deleteContactAsync } from 'expo-contacts';
const contactId = '1234567890';
try {
await deleteContactAsync(contactId);
console.log('Contact deleted successfully');
} catch (error) {
console.error('Failed to delete contact:', error);
}
Note: The contact ID must be a valid identifier returned from
getContactsAsync.
Warning: This operation is irreversible. Ensure the user confirms before deletion.
7. Searching Contacts
| Property | Description | Example |
|---|---|---|
| query | Search query string to filter contacts by name or phone number. | "John" |
| phoneNumber | Search by phone number (exact match). | "+1234567890" |
| Search by email address (exact match). | "john@example.com" |
|
| fields | Array of fields to return in the search results. | ["name", "phoneNumbers"] |
Example: Searching Contacts by Name
import * as Contacts from 'expo-contacts';
const searchResults = await Contacts.getContactsAsync({
fields: [Contacts.Fields.Name, Contacts.Fields.PhoneNumbers],
query: 'John'
});
console.log(searchResults);
Example: Searching Contacts by Phone Number
import * as Contacts from 'expo-contacts';
const searchResults = await Contacts.getContactsAsync({
fields: [Contacts.Fields.Name, Contacts.Fields.PhoneNumbers],
phoneNumber: '+1234567890'
});
console.log(searchResults);
Note: The
query parameter performs a case-insensitive search across name and phone number fields.
8. Getting Contact Groups
| Property | Description | Notes |
|---|---|---|
| group.id | Unique identifier for the contact group | String, read-only |
| group.name | Name of the contact group | String, read-only |
| group.contactIds | Array of contact IDs belonging to the group | Array of strings, read-only |
Example: Fetching Contact Groups
import * as Contacts from 'expo-contacts';
const getContactGroups = async () => {
const { data } = await Contacts.getGroupsAsync();
return data;
};
const groups = await getContactGroups();
console.log(groups);
Note: Requires
CONTACTS permission to access contact groups.
9. Handling Contact Fields
| Field | Description | Values | Notes |
|---|---|---|---|
| id | Unique identifier for the contact | string |
Read-only field |
| name | Contact's name | string |
Can be formatted as {givenName, familyName, middleName} |
| phoneNumbers | List of phone numbers associated with the contact | Array<{label: string, number: string}> |
Each phone number includes a label (e.g., "home", "work") |
| emails | List of email addresses associated with the contact | Array<{label: string, email: string}> |
Each email includes a label (e.g., "home", "work") |
| addresses | Physical addresses of the contact | Array<{label: string, street: string, city: string, region: string, postCode: string, country: string}> |
Each address includes a label and full address fields |
| urls | Website or URL links for the contact | Array<{label: string, url: string}> |
Each URL includes a label (e.g., "personal", "work") |
| birthday | Birthday of the contact in ISO format | string (YYYY-MM-DD) |
Optional field |
| note | Additional notes about the contact | string |
Optional field |
Example: Retrieving Contact Fields
import * as Contacts from 'expo-contacts';
const { data } = await Contacts.getContactsAsync({
fields: [Contacts.Fields.Name, Contacts.Fields.PhoneNumbers],
});
console.log(data[0].name); // "John Doe"
console.log(data[0].phoneNumbers); // [{ label: "home", number: "(555) 123-4567" }]
Example: Adding a New Contact with Fields
import * as Contacts from 'expo-contacts';
const newContact = {
name: "Jane Smith",
phoneNumbers: [
{ label: "work", number: "(555) 987-6543" }
],
emails: [
{ label: "personal", email: "jane@example.com" }
],
addresses: [
{
label: "home",
street: "123 Main St",
city: "Anytown",
region: "CA",
postCode: "12345",
country: "USA"
}
]
};
const contactId = await Contacts.createContactAsync(newContact);
console.log("Created contact with ID:", contactId);
Note: Not all fields are supported on every platform. For example,
birthday and note fields might not be available on all devices or operating systems.
10. Opening Contact Form
| Property | Description | Values |
|---|---|---|
| contactId | Unique identifier for the contact | null or string |
| fields | Fields to include in the contact form | Array<string> |
| title | Title of the contact form screen | string |
Example: Opening Contact Form
import * as Contacts from 'expo-contacts';
const openContactForm = async () => {
const result = await Contacts.openContactFormAsync({
title: 'Add New Contact',
fields: [Contacts.ContactField.PhoneNumber, Contacts.ContactField.Email],
});
if (result) {
console.log('Contact created:', result);
}
};
11. Formatting Contact Names
| Property | Description | Example |
|---|---|---|
| name | Contact's full name | "John Doe" |
| firstName | First name of the contact | "John" |
| lastName | Last name of the contact | "Doe" |
| middleName | Middle name of the contact | "Michael" |
| prefix | Prefix of the contact's name (e.g., "Dr.", "Mr.") | "Dr." |
| suffix | Suffix of the contact's name (e.g., "Jr.", "III") | "Jr." |
Example: Formatting Contact Name
import * as Contacts from 'expo-contacts';
const contact = await Contacts.getContactByIdAsync('contact-id-here');
const formattedName = `${contact.prefix} ${contact.firstName} ${contact.middleName} ${contact.lastName} ${contact.suffix}`.trim();
console.log(formattedName); // "Dr. John Michael Doe Jr."
12. Handling Contact Images
| Property | Description | Notes |
|---|---|---|
| image | string |
URI to the contact's image |
| imageAvailable | boolean |
Indicates if image is available for contact |
Example: Fetching Contact Image
import * as Contacts from 'expo-contacts';
const contactId = 'contact-id-here';
const { image } = await Contacts.getContactByIdAsync(contactId);
if (image) {
console.log('Image URI:', image);
} else {
console.log('No image available');
}
Note: Image URIs may require additional permissions or handling depending on the platform (iOS/Android).