Вопрос или проблема
Я продолжаю получать ошибку ниже
ОШИБКА ReferenceError: Свойство 'crypto' не существует, js движок: hermes
в ContextNavigator (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:145632:24)
в ExpoRoot (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:145588:28)
в App
в ErrorToastContainer (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:242934:24)
в ErrorOverlay
в withDevTools(ErrorOverlay) (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:242437:27)
в RCTView
в View (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:41517:43)
в RCTView
в View (http://localhost:8081/node_modules/expo-router/entry.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&app=com.testlio.deviceverificationapp.Clip&transform.routerRoot=app&transform.engine=hermes&transform.bytecode=true:41517:43)
всякий раз, когда я пытаюсь запустить свое React Native Expo
приложение в Xcode. Я не знаю, почему. Однако оно работает, когда я запускаю npm run ios
в своем vscode
Я пробовал снова сгенерировать файл pod, удалить hermes
из определения файла pod, но это все равно не работает в Xcode.
Вот мой компонент React Native Expo
import * as crypto from 'crypto';
import React, { useEffect, useState } from 'react';
import { View, Text, Image, StyleSheet } from 'react-native';
import DeviceInfo from 'react-native-device-info';
import * as Device from 'expo-device';
import { useVerifyDeviceMutation } from './verifyDeviceQuery.generated';
type DeviceVerificationPayload = {
deviceVariantIdentifier: string;
deviceOsVersion: string;
};
const encrypt = (payload: DeviceVerificationPayload) => {
const algorithm = ‘aes-256-cbc’;
const encryptionAlgoKey = ‘Key’;
const encryptionKey = base64ToUtf8(encryptionAlgoKey);
const key = CryptoJS.SHA256(encryptionKey);
const iv = CryptoJS.lib.WordArray.create(key.words.slice(0, 4));
const stringifiedPayload = JSON.stringify(payload);
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(stringifiedPayload, 'utf8', 'hex');
encrypted += cipher.final('hex'); return encrypted;
return encrypted;
};
export default function HomeScreen() {
const deviceVerificationGuid = 'deviceVerificationGuid';
const [isVerifying, setIsVerifying] = useState<boolean>(true);
const [deviceVerificationFailure, setDeviceVerificationFailure] = useState<boolean>(false);
const [verifyDevice, { loading }] = useVerifyDeviceMutation({
onCompleted: () => {
setIsVerifying(false);
},
onError: (data) => {
setIsVerifying(false);
setDeviceVerificationFailure(true);
}
});
useEffect(() => {
const deviceVariantIdentifier = Device.modelName || '';
const deviceOsVersion = Device.osVersion || '';
const signature = encrypt({
deviceVariantIdentifier,
deviceOsVersion
});
verifyDevice({
variables: {
input: {
deviceVariantIdentifier,
deviceOsVersion,
signature,
deviceVerificationGuid
}
}
});
}, [deviceVerificationGuid, verifyDevice]);
if (!deviceVerificationGuid) {
return (
<View style={styles.container}>
<Image source={require('./assets/loadicon.gif')} style={styles.image} />
</View>
);
}
return (
<View style={styles.container}>
Логика пользовательского интерфейса
</View>
);
}
Вышеуказанное работает всякий раз, когда я запускаю npm run ios
, но конкретно не работает, когда я запускаю его на Xcode.
Не совсем уверен, почему это происходит
Проблема в
import * as crypto from 'crypto';
Модуль Crypto
доступен только в приложениях javascript
на стороне сервера, т.е. в приложениях, которые запускаются на node
. React
и React Native
являются клиентскими, поэтому нативная библиотека crypto не будет работать. Вы можете вместо этого использовать встроенную библиотеку expo
crypto
или использовать сторонний пакет, такой как crypto-js
Ответ или решение
Ошибка "crypto not found" в вашему проекте React Native Expo связана с попыткой использовать модуль crypto
, который доступен только в серверной среде Node.js. В контексте React и React Native, которые ориентированы на клиентскую часть, использование встроенного модуля crypto
невозможно, что и приводит к возникновению этой ошибки, особенно при запуске проекта через Xcode.
Рекомендации по решению проблемы
-
Использование библиотеки Expo Crypto:
Expo предоставляет собственный модуль для работы с криптографией, который можно использовать вместо стандартногоcrypto
. Чтобы это сделать, внесите следующие изменения в ваш код:Замените строку импорта:
import * as crypto from 'crypto';
на
import * as Crypto from 'expo-crypto';
После чего обновите вашу функцию
encrypt
для использования методов изexpo-crypto
. -
Как использовать
expo-crypto
:
Пример вашего кода с учетом изменений может выглядеть следующим образом:import * as Crypto from 'expo-crypto'; import { Buffer } from 'buffer'; const encrypt = async (payload) => { const algorithm = 'aes-256-cbc'; const encryptionAlgoKey = 'Key'; const encryptionKey = base64ToUtf8(encryptionAlgoKey); const key = CryptoJS.SHA256(encryptionKey); const iv = CryptoJS.lib.WordArray.create(key.words.slice(0, 4)); const stringifiedPayload = JSON.stringify(payload); // Использование expo-crypto для криптографии const cipher = await Crypto.getRandomBytesAsync(32); // Получение случайного байта const encrypted = // Здесь ваша логика шифрования с использованием crypto из Expo return encrypted; };
-
Использование crypto-js:
Если вам нужно больше возможностей для криптографии или если вы хотите оставить много кода без изменений, вы можете использовать библиотекуcrypto-js
. Для установки выполните:npm install crypto-js
Затем импортируйте необходимые алгоритмы в свой файл:
import CryptoJS from 'crypto-js';
Измените логику шифрования в функции
encrypt
, используя методы изcrypto-js
.
Заключение
Если вы продолжаете сталкиваться с ошибками при запуске вашего приложения через Xcode, убедитесь, что вы очищаете кэш и перестраиваете проект. Это можно сделать с помощью следующих команд:
cd ios
pod install
cd ..
expo start -c
Следуя предложенным рекомендациям, вы сможете избавиться от ошибки ReferenceError: Property 'crypto' doesn't exist
и успешно запустить ваше React Native приложение с использованием Expo.