Expo开发中如何条件导入RevenueCat以规避ExpoGo运行异常?
解决ExpoGo环境下条件导入react-native-purchases无效的问题
你的代码无效的核心原因是ES模块的静态import语句会在代码执行前被预解析,不管你写的if条件是什么,ExpoGo环境下依然会尝试导入react-native-purchases库,进而触发原生模块不兼容的异常。以下是几种可行的解决思路:
1. 使用动态导入(推荐)
动态导入import()是运行时执行的,只有满足条件才会加载目标模块,完美适配你的需求。
组件顶层初始化(配合立即执行异步函数)
import { IsExpoGo, RevenueCatAPIKeys } from "./lib/constants"; let Purchases = null; let PurchasesOffering = null; // 立即执行异步函数处理导入 (async () => { if (!IsExpoGo) { const module = await import('react-native-purchases'); Purchases = module.default; PurchasesOffering = module.PurchasesOffering; // 初始化RevenueCat Purchases.configure({ apiKey: RevenueCatAPIKeys[process.env.NODE_ENV] }); } })();
React组件内使用(结合useEffect)
如果在React组件中,需要将导入逻辑放在useEffect中避免顶层await问题:
import { useEffect, useState } from 'react'; import { IsExpoGo, RevenueCatAPIKeys } from "./lib/constants"; const PurchaseScreen = () => { const [revenueCat, setRevenueCat] = useState(null); useEffect(() => { const initRevenueCat = async () => { if (!IsExpoGo) { const module = await import('react-native-purchases'); const Purchases = module.default; Purchases.configure({ apiKey: RevenueCatAPIKeys[process.env.NODE_ENV] }); setRevenueCat({ Purchases, PurchasesOffering: module.PurchasesOffering }); } }; initRevenueCat(); }, []); // 使用时先判断模块是否加载完成 const fetchOffering = async () => { if (!revenueCat?.Purchases) return; const offering = await revenueCat.Purchases.getOfferings(); // 处理业务逻辑 }; return ( <div> {!IsExpoGo && ( <button onClick={fetchOffering}>获取商品套餐</button> )} </div> ); };
2. 拆分组件隔离导入
创建一个仅在非ExpoGo环境下渲染的组件,将react-native-purchases的静态导入放在该组件内部,ExpoGo环境下不会渲染这个组件,自然不会触发导入:
封装RevenueCat逻辑组件
// components/RevenueCatHandler.js import Purchases, { PurchasesOffering } from 'react-native-purchases'; import { RevenueCatAPIKeys } from "../lib/constants"; // 初始化配置 Purchases.configure({ apiKey: RevenueCatAPIKeys[process.env.NODE_ENV] }); export const RevenueCatHandler = ({ onFetchOffering }) => { const fetchOffering = async () => { const offering = await Purchases.getOfferings(); onFetchOffering(offering); }; return ( <button onClick={fetchOffering}>获取商品套餐</button> ); };
主组件中条件渲染
import { IsExpoGo } from "./lib/constants"; import { RevenueCatHandler } from './components/RevenueCatHandler'; const App = () => { return ( <div> {/* 仅在非ExpoGo环境下渲染购买组件 */} {!IsExpoGo && ( <RevenueCatHandler onFetchOffering={(offering) => console.log(offering)} /> )} {/* 其他通用UI */} </div> ); };
3. 使用CommonJS的require导入
如果你的项目兼容CommonJS语法,也可以用require替代静态import,它是运行时加载的:
import { IsExpoGo, RevenueCatAPIKeys } from "./lib/constants"; let Purchases = null; let PurchasesOffering = null; if (!IsExpoGo) { const purchasesModule = require('react-native-purchases'); Purchases = purchasesModule.default; PurchasesOffering = purchasesModule.PurchasesOffering; Purchases.configure({ apiKey: RevenueCatAPIKeys[process.env.NODE_ENV] }); }
内容的提问来源于stack exchange,提问作者VAAA
相关产品推荐
相关产品推荐

