我正在尝试在手机(iPhone)上安装我的react-native应用程序。它安装正常但随后在此错误消息时崩溃 -
navigator
如果我然后启用远程js调试,它会重新加载,一切正常。我禁用远程调试,应用程序恢复崩溃。知道这里可能会发生什么吗?
更新 - 罪魁祸首代码在fbjs包中 - https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getDocumentScrollElement.js
他们检查是否定义了navigator.userAgent.indexOf
,然后尝试访问其上的第二级属性 - navigator.userAgent
。
我可以以某种方式伪造{{1}}或向fbjs发送PR。
答案 0 :(得分:7)
navigator
是浏览器中提供的全局Web API。这在React Native中不可用,因为它不是Web浏览器。所有Web API都不是全局环境的一部分。这就是navigator.userAgent.indexOf
抛出undefined
错误的原因。
现在,在远程调试JS时,程序运行正常的原因是,当您进行远程调试时,React Native将切换到使用Chrome提供的JavaScript引擎(或者您正在调试的任何内容)而不是核心引擎。因此,在调试时,您将可以访问浏览器通常具有的全局Web API。
这是一个非常棘手的问题,因为大多数人一直在调试开启的情况下经常绊倒人们。经验法则:React Native不是浏览器。不要使用在进行Web开发时通常使用的任何全局变量,并且您将避免大多数这些类型的错误。
如果您想在React Native的JavaScript引擎中看到这些全局变量是如何被填充的(通常是空对象),您需要查看initializeCore.js。在这里,您可以看到React Native将像这样填充navigator
:
// Set up Geolocation
let navigator = global.navigator;
if (navigator === undefined) {
global.navigator = navigator = {};
}
// see https://github.com/facebook/react-native/issues/10881
polyfillObjectProperty(navigator, 'product', () => 'ReactNative');
polyfillObjectProperty(navigator, 'geolocation', () => require('Geolocation'));
修改:要回答后续行动并提供解决方法。
您可以对其进行填充,但在导入index.js
(应用程序的根目录)中的任何其他文件之前,您需要执行此操作。这是how it's done in node-libs-react-native
及其globals.js文件,他们也设置了默认的用户代理字符串。通过执行以下操作,您可以实现相同的结果:
创建文件以保留垫片globals.js
:
global.navigator.userAgent = 'React Native';
导入/在导入index.js
中的任何其他文件之前需要它:
import { AppRegistry } from "react-native";
import globals from "./globals";
import App from "./App";
AppRegistry.registerComponent("RNSandbox", () => App);
如果由于某种原因您希望userAgent
不同或依赖于您是否正在调试,您可以将自己的逻辑添加到globals.js
。