Skip to main content

Searching...

Tools
Articles
View All Results

Developer Lab · React Native

Generate UUID in React Native

React Native has no native crypto.randomUUID() - you need a polyfill. The standard approach is react-native-get-random-values + uuid, or expo-crypto on Expo projects.

Quick Reference

Approach Works on Expo Use Case
rn-get-random-values + uuid iOS + Android Yes (bare) Recommended for bare React Native
expo-crypto iOS + Android + Web Yes (managed) Recommended for Expo managed workflow
react-native-uuid iOS + Android Yes Simpler API, single package

Primary Implementation

Production Ready
javascript
// STEP 1: Install packages
// npm install react-native-get-random-values uuid

// STEP 2: Import the polyfill at the TOP of your entry file (index.js or App.js)
// This MUST be the very first import - before anything else
import 'react-native-get-random-values';

// STEP 3: Now you can use the uuid package normally
import { v4 as uuidv4 } from 'uuid';

// Generate a UUID v4
const id = uuidv4();
console.log(id);
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"

// Generate multiple
const ids = Array.from({ length: 5 }, () => uuidv4());

// Validate a UUID
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const isValidUUID = (str) => UUID_REGEX.test(str);

All Approaches

Expo managed workflow - expo-crypto

javascript
// npx expo install expo-crypto
import * as Crypto from 'expo-crypto';

// Generate a UUID v4 - works on iOS, Android, and Web
const id = Crypto.randomUUID();
console.log(id);
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"

// expo-crypto also provides randomBytes for custom entropy needs
const bytes = await Crypto.getRandomBytesAsync(16);

react-native-uuid - single package, no polyfill needed

javascript
// npm install react-native-uuid
import uuid from 'react-native-uuid';

// No polyfill import needed - handles entropy internally
const id = uuid.v4();
console.log(id);
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"

TypeScript - typed UUID generation

typescript
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';

// Branded type for type safety
type ItemId = string & { readonly _brand: 'ItemId' };

function createItemId(): ItemId {
    return uuidv4() as ItemId;
}

interface ListItem {
    id: ItemId;
    title: string;
    completed: boolean;
}

function createItem(title: string): ListItem {
    return { id: createItemId(), title, completed: false };
}

Real-World Use Cases

1. FlatList with stable item keys

javascript
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import { FlatList, Text, TouchableOpacity } from 'react-native';
import { useState } from 'react';

export default function TodoList() {
    const [todos, setTodos] = useState([]);

    const addTodo = (text) => {
        setTodos(prev => [...prev, { id: uuidv4(), text, done: false }]);
    };

    return (
        <FlatList
            data={todos}
            keyExtractor={item => item.id}  // UUID as stable key
            renderItem={({ item }) => <Text>{item.text}</Text>}
        />
    );
}

2. AsyncStorage - unique device ID

javascript
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
import AsyncStorage from '@react-native-async-storage/async-storage';

const DEVICE_ID_KEY = '@device_id';

async function getDeviceId() {
    let id = await AsyncStorage.getItem(DEVICE_ID_KEY);
    if (!id) {
        id = uuidv4();
        await AsyncStorage.setItem(DEVICE_ID_KEY, id);
    }
    return id;
}

3. Optimistic UI - assign ID before API call

javascript
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';

async function addComment(postId, text, setComments) {
    const tempId = uuidv4();
    const optimisticComment = { id: tempId, text, status: 'pending' };

    // Immediately show in UI
    setComments(prev => [...prev, optimisticComment]);

    try {
        const response = await fetch(`/api/posts/${postId}/comments`, {
            method: 'POST',
            headers: { 'Idempotency-Key': tempId },
            body: JSON.stringify({ text }),
        });
        const saved = await response.json();
        // Replace temp with server-confirmed comment
        setComments(prev => prev.map(c => c.id === tempId ? saved : c));
    } catch {
        // Remove on failure
        setComments(prev => prev.filter(c => c.id !== tempId));
    }
}

Common Mistakes

Not importing the polyfill first

import 'react-native-get-random-values' MUST be the very first import in your entry file (index.js). If it comes after other imports, the polyfill may not be applied in time and uuid will throw an error about missing crypto.getRandomValues.

Using Math.random() for IDs

Math.random() is not CSPRNG-backed and only provides ~53 bits of entropy. It is not suitable for unique IDs in any production app. Always use the polyfill + uuid approach.

Forgetting to run pod install after installing the polyfill

react-native-get-random-values has native iOS code. After npm install, run cd ios && pod install to link the native module. Skipping this causes a crash on iOS.

Using the polyfill approach in Expo managed workflow

In Expo managed workflow, you cannot use native modules that require pod install. Use expo-crypto instead - it's part of the Expo SDK and works without ejecting.

How It Works

React Native's JavaScript engine (Hermes or JSC) does not expose crypto.getRandomValues() by default. The react-native-get-random-values polyfill bridges to the native OS CSPRNG - SecRandomCopyBytes on iOS and SecureRandom on Android.

Once the polyfill is in place, the uuid package works exactly as it does in a browser or Node.js environment.

expo-crypto takes a different approach - it calls the native module directly without needing a global polyfill, making it cleaner for Expo projects.

Output Example

uuidv4()

f47ac10b-58cc-4372-a567-0e02b2c3d479

Crypto.randomUUID() (expo-crypto)

f47ac10b-58cc-4372-a567-0e02b2c3d479

Best Practices, Performance, and Security

Best practices

Put the polyfill import as the absolute first line of index.js.

Use expo-crypto in Expo managed workflow - no native linking needed.

Use UUIDs as keyExtractor in FlatList for stable, efficient list rendering.

Performance

UUID generation is fast - the native bridge call is minimal overhead. Generating UUIDs for list items, form fields, or optimistic updates has no measurable impact on UI performance.

The polyfill is synchronous - no async/await needed for UUID generation.

Security

iOS entropy source: SecRandomCopyBytes - Apple's CSPRNG. Cryptographically secure.

Android entropy source: java.security.SecureRandom - backed by the OS entropy pool. Cryptographically secure.

Suitable for session tokens, device IDs, and API keys in mobile apps.

Installation

Bare React Native

bash
npm install react-native-get-random-values uuid
cd ios && pod install

Import react-native-get-random-values before uuid in your entry file.

Expo managed workflow

bash
npx expo install expo-crypto

Use expo-crypto for UUID generation in Expo managed projects.

Frequently Asked Questions

How do I generate a UUID in React Native?

React Native has no native crypto.getRandomValues, so install react-native-get-random-values and import it once at the top of your entry file, then use the uuid package (import { v4 as uuidv4 } from 'uuid'). In Expo projects you can call Crypto.randomUUID() from expo-crypto instead. Never use Math.random() for IDs, since it is not cryptographically secure.

Is uuidv4() cryptographically secure?

Yes. uuidv4() uses the platform CSPRNG (operating system secure random source), suitable for session tokens, API keys, and idempotency keys. Do not use non-cryptographic random sources for security-sensitive identifiers.

What is the difference between UUID v4 and v7 in React Native?

UUID v4 (uuidv4() or equivalent) is fully random and not sortable. UUID v7 embeds a millisecond timestamp for chronological sorting (RFC 9562). Use v4 for general-purpose IDs; use v7 for database primary keys at scale.

Do I need to install a package for UUID generation in React Native?

A package or library install may be required. See the Installation section for the recommended approach in React Native.

How do I validate a UUID string in React Native?

Use the platform's UUID parse/validation function, or test against the RFC 4122 regex: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i. Always validate external input at API boundaries.

Should I use UUIDs as database primary keys in React Native applications?

UUIDs work well as primary keys for distributed systems. Prefer native UUID/BINARY(16) column types over VARCHAR(36). For very large tables, consider UUID v7 for better B-tree insert locality.

Can I generate UUIDs in React Native without a network connection?

Yes. UUID generation uses local OS entropy sources and does not require network access. Each call is independent and thread-safe on modern platforms.

What output formats are available in React Native?

The standard hyphenated lowercase string (36 chars) is the default. Most APIs also support 32-char hex (no hyphens) and 16-byte binary formats. Use string format for APIs and binary for database storage.

What RFC standards apply to React Native UUID generation?

Version 4 UUIDs follow RFC 4122. UUID v7 follows RFC 9562 (May 2024). Ensure your chosen method produces compliant version and variant bits.

When should I avoid UUID v1?

Avoid UUID v1 in security-sensitive contexts - it embeds MAC address and timestamp information. Prefer v4 (uuidv4() or equivalent) unless you need legacy Cassandra timeuuid compatibility.

Key definitions

UUID
128-bit universally unique identifier, usually shown as 36 hex characters with hyphens.
CSPRNG
Cryptographically secure pseudo-random number generator - the entropy source behind secure UUID generation.
RFC 4122
IETF standard defining UUID versions 1 through 5. Version 4 is random.
RFC 9562
IETF standard adding UUID versions 6, 7, and 8. Version 7 is time-ordered.