Scanning database...
Tools
Articles

No matches found for ""

View All Results
Home Dev Lab react native
Developer Lab

UUID in React Native

Production-ready implementation guide with CSPRNG-backed code snippets.



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 snippet — bare React Native
// 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 snippet
// 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 snippet
// 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 snippet
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 snippet
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 snippet
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 snippet
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

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.

Installation

# Bare React Native
npm install react-native-get-random-values uuid
cd ios && pod install
# Expo managed workflow
npx expo install expo-crypto
# Simpler alternative (any RN project)
npm install react-native-uuid

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.