React native 当远程调试被禁用时,应用程序在启动时崩溃

React native 当远程调试被禁用时,应用程序在启动时崩溃,react-native,react-native-ios,React Native,React Native Ios,我正在尝试在我的手机(iPhone)上安装我的react本机应用程序。它安装正常,但在启动时崩溃,并显示此错误消息- undefined is not an object (evaluating 'navigator.userAgent.indexOf') <unknown> :12:71 loadModuleImplementation require.js:213:12 <unknown> getScrollPosition.js:12:3

我正在尝试在我的手机(iPhone)上安装我的react本机应用程序。它安装正常,但在启动时崩溃,并显示此错误消息-

undefined is not an object (evaluating 'navigator.userAgent.indexOf')

<unknown>
     :12:71
loadModuleImplementation
    require.js:213:12
<unknown>
    getScrollPosition.js:12:31
undefined不是对象(正在评估'navigator.userAgent.indexOf')
:12:71
加载模块实现
require.js:213:12
getScrollPosition.js:12:31
如果我随后启用远程js调试,它将重新加载,一切正常。如果禁用远程调试,应用程序将返回崩溃状态。知道这里会发生什么吗

更新-罪犯代码在fbjs包中-

他们检查是否定义了
navigator
,然后尝试访问它的第二级属性-
navigator.userAgent.indexOf

我可以以某种方式伪造
navigator.userAgent
,或者向fbjs发送PR

是一种在浏览器中可用的全局Web API。这在React Native中不可用,因为它不是web浏览器。并非所有Web API都是全局环境的一部分。这就是为什么
navigator.userAgent.indexOf
抛出
undefined
错误的原因

现在,远程调试JS时程序运行良好的原因是React Native将切换到使用Chrome提供的JavaScript引擎(或任何您正在调试的引擎),而不是远程调试时使用的核心引擎。因此,在调试时,您可以访问浏览器通常具有的全局Web API

这是一个非常棘手的问题,当大多数人在开发过程中一直打开调试时,它常常会让人绊倒。经验法则:React Native不是浏览器。不要使用在进行web开发时通常使用的任何全局变量,这样可以避免大多数此类gotcha错误

如果您想在React Native的JavaScript引擎中看到这些全局变量是如何多填充的(通常是空对象),您需要了解一下。在这里您可以看到React Native将polyfill
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
(应用程序的根目录)中的任何其他文件之前需要进行填充。这是他们的文件,他们也设置了默认的用户代理字符串。对此,您可以通过执行以下操作来实现相同的结果:

  • 创建用于保存垫片的文件,
    globals.js

    global.navigator.userAgent = 'React Native';
    
    import { AppRegistry } from "react-native";
    import globals from "./globals";
    import App from "./App";
    
    AppRegistry.registerComponent("RNSandbox", () => App);
    
  • 在导入
    index.js中的任何其他文件之前导入/要求它:

    global.navigator.userAgent = 'React Native';
    
    import { AppRegistry } from "react-native";
    import globals from "./globals";
    import App from "./App";
    
    AppRegistry.registerComponent("RNSandbox", () => App);
    

  • 如果出于某种原因,您希望
    userAgent
    不同或取决于您是否正在调试,您可以将自己的逻辑添加到
    globals.js

    中,您可以发布
    getScrollPosition.js:12:31
    和所需的模块代码吗?这不是我的代码。我认为这是第三方图书馆之一。可能是德拉夫特的。我会检查并返回。它来自fbjs-:)draftjs依赖于某些浏览器API,如“”。Michael Cheng的回答解释了为什么它在没有附加调试程序的情况下无法工作。它只检查导航器是否未定义,然后继续访问第二级属性(navigator.userAgent.indexOf)。当调试器被附加时,它会找到附加到navigator的userAgent属性,但没有找到它。是的,我知道了。这就是罪魁祸首文件-我试图通过在index.js文件中添加global.navigator.userAgent='dummyAgent'来放置一个虚拟的userAgent,但没有成功。似乎太晚了。我应该把我的polyfill代码放在哪里?有什么建议吗?Michael?@MukeshSoni正在做一些事情。我为
    userAgent
    编辑了一个填充虚拟值的方法。谢谢!成功了。我不明白为什么当我把同一行(global.navigator.userAgent='React Native')直接放在index.js中的第一条语句中时它不起作用?@MukeshSoni这是一个很好的问题,但它确实超出了这个问题的范围。我想我会自己发布一个关于这个的问题,因为我没有时间深入讨论。我的猜测是,它与导入、范围和巴别塔有关。查看App.js文件中的评论,看看我在说什么。