PR
React Native react-native-get-random-valuesreact-native-uuiduuidv4

React Native で UUID を安全に生成する方法〜Expo〜

plum-4917370_1920 React Native

この記事は 2020 年当時の記録です(2026 年 7 月 追記・重要)

最初に、はっきりお伝えしておきます。本文の後半で紹介している seed() を使う方法は、現在は使わないでください。当時エラーを回避するために書いたものですが、生成される UUID の品質に問題があります。

1. seed() を使ってはいけない理由

本文の seed()Math.random() を元にしていますが、それだけではありません。値の作り方を見てください。

Math.floor((Math.random() * 100) / 3.92)

この式が返すのは 0 から 25 までの値です。UUID の各バイトは本来 0 から 255 の範囲を取るはずなので、取りうる値の幅が 10 分の 1 に狭まっています。

本文に載せている出力例をご覧ください。

0e0c1207-0f0b-4a17-9309-110c06141608
060a090b-0c03-4900-9506-010b0b010705

2 桁ずつ区切って見ると、00 から 19 の範囲しか出ていません。本来ランダムであるはずの部分に、はっきりした偏りがあります。UUID の一意性は「まず衝突しない」という前提の上に成り立っているので、この偏りは前提そのものを崩します。

加えて Math.random() は暗号用途に使えるものではありません。トークンやソルトなど、推測されては困る値に使うのは避けてください。

2. 現在はこれ 1 行で済みます

Expo SDK 48 で expo-randomexpo-crypto に統合され、UUID の生成関数がそのまま用意されました。ネイティブ側の安全な乱数生成器を使います。

import * as Crypto from 'expo-crypto';

const id = Crypto.randomUUID();

uuid パッケージも react-native-get-random-values も要りません。Expo を使っているなら、これがいちばん素直です。

3. uuid パッケージを使い続ける場合

本文の前半、react-native-get-random-values を読み込んでから uuid を使う方法は今も有効です。このライブラリは現在もメンテナンスされています。

// index.js の先頭で
import 'react-native-get-random-values';

// 使うところで
import { v4 as uuidv4 } from 'uuid';
uuidv4();

expo-crypto の乱数を uuid に渡す形も取れます。ポリフィルを増やしたくない場合の選択肢です。

import { getRandomValues } from 'expo-crypto';
import { v4 as uuidv4 } from 'uuid';

export const v4 = () => {
  const random = new Uint8Array(16);
  getRandomValues(random);
  return uuidv4({ random });
};

いずれの方法でも、seed() を渡す必要はありません。本文のあの関数は、当時の回避策として読んでいただければと思います。

※ 上記は 2026 年 7 月時点の Expo 公式ドキュメントおよび各パッケージの記載に基づく整理であり、当方の環境での再検証は行っていません。

スポンサーリンク

環境・関連リソース

  • macOS Catalina 10.15.3
  • Node.js v12.14.1
  • expo 36.0.0
  • react-native-get-random-values 1.3.0
  • uuid 7.0.2

uuidを使う

ユニークなランダム ID を生成してくれる uuid を React Native で使おうとすると以下のエラーが発生します。

Error:
crypto.getRandomValues() not supported.

↑リンクの指示通り react-native-get-random-values をインストールして uuid の前に import しておきます。

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

アプリをリロードすると、今度は以下のようなエラーが発生します。

Error:
TypeError: null is not an object (evaluating 'RNGetRandomValues.getRandomBase64')

こうなると使えないな〜と思い、
react-native-uuid に変えてみたらエラーは解消したものの、今度は以下の警告メッセージが発生してしまいます。

警告:
[SECURITY] node-uuid: crypto not usable, falling back to insecure Math.random()

これも使えない!

uuid のエラーを解消して使う

null is not an object エラーを解消するため、16 桁のランダム数字 ( 0 – 255 ) を生成して uuid のシードとして与えます。

// src/utils/uuidSeed.js

export const seed = () => {
  const one = Math.floor((Math.random() * 100) / 3.92);
  const two = Math.floor((Math.random() * 100) / 3.92);
  const three = Math.floor((Math.random() * 100) / 3.92);
  const four = Math.floor((Math.random() * 100) / 3.92);
  const five = Math.floor((Math.random() * 100) / 3.92);
  const six = Math.floor((Math.random() * 100) / 3.92);
  const seven = Math.floor((Math.random() * 100) / 3.92);
  const eight = Math.floor((Math.random() * 100) / 3.92);
  const nine = Math.floor((Math.random() * 100) / 3.92);
  const ten = Math.floor((Math.random() * 100) / 3.92);
  const eleven = Math.floor((Math.random() * 100) / 3.92);
  const twelve = Math.floor((Math.random() * 100) / 3.92);
  const thirteen = Math.floor((Math.random() * 100) / 3.92);
  const fourteen = Math.floor((Math.random() * 100) / 3.92);
  const fifteen = Math.floor((Math.random() * 100) / 3.92);
  const sixteen = Math.floor((Math.random() * 100) / 3.92);
  return [
    one,
    two,
    three,
    four,
    five,
    six,
    seven,
    eight,
    nine,
    ten,
    eleven,
    twelve,
    thirteen,
    fourteen,
    fifteen,
    sixteen
  ];
};

使い方:

// seed をインポートします。
import "react-native-get-random-values";
import { v4 as uuidv4 } from "uuid";
import { seed } from "../utils/uuidSeed";

// 以下のように使用します。
uuidv4({ random: seed() })

uuidv4({ random: seed() })の実行結果例:

0e0c1207-0f0b-4a17-9309-110c06141608
060a090b-0c03-4900-9506-010b0b010705
0814040d-0413-4805-8217-080d0e000804
09130c13-0d18-4b04-9104-111312020e14

コメント

タイトルとURLをコピーしました