Javascript react项目中的ES6循环依赖关系

Javascript react项目中的ES6循环依赖关系,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,我刚刚使用react native设置了一个小测试项目。这对我来说是全新的(包括ECMAScript 6)。Eslint告诉我一些关于“循环依赖”的事情,我不知道如何解决这个问题。尽管如此,该准则仍在发挥作用 my package.json: ... "dependencies": { "axios": "^0.19.0", "node-sass": "^4.12.0", "react": "16.8.3", "react-native": "0.59.9",

我刚刚使用react native设置了一个小测试项目。这对我来说是全新的(包括ECMAScript 6)。Eslint告诉我一些关于“循环依赖”的事情,我不知道如何解决这个问题。尽管如此,该准则仍在发挥作用

my package.json:

...
"dependencies": {
    "axios": "^0.19.0",
    "node-sass": "^4.12.0",
    "react": "16.8.3",
    "react-native": "0.59.9",
    "react-navigation": "^3.11.0"
},
"devDependencies": {
    "@babel/core": "7.4.5",
    "@babel/runtime": "7.4.5",
    "babel-eslint": "^10.0.1",
    "babel-jest": "24.8.0",
    "babel-plugin-module-resolver": "^3.2.0",
    "eslint": "^5.16.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-import-resolver-babel-module": "^5.1.0",
    "eslint-plugin-import": "^2.17.3",
    "eslint-plugin-jsx-a11y": "^6.2.1",
    "eslint-plugin-react": "^7.13.0",
    "jest": "24.8.0",
    "metro-react-native-babel-preset": "0.54.1",
    "react-dom": "^16.8.6",
    "react-test-renderer": "16.8.3"
},
...

src/index.jsx
是主jsx文件:

import { Comp1 } from 'components';
...

我创建了一个
src/components/index.jsx
来支持导入,比如

import { Comp1, Comp2, Comp3 } from 'components'
而不是

import { Comp1 } from 'components/comp1';
import { Comp2 } from 'components/comp2';
import { Comp3 } from 'components/comp3';
文件
src/components/index.jsx
如下所示:

export * from './button';
export * from './comp1';
...

src/components/button/index.jsx

import React from 'react';
import {
  Text,
  TouchableOpacity
} from 'react-native';
import style from './style';

const Button = ({ onPress, children }) => {
  const {
    buttonStyle,
    textStyle
  } = style;

  return (
    <TouchableOpacity onPress={onPress} style={buttonStyle}>
      <Text style={textStyle}>
        {children}
      </Text>
    </TouchableOpacity>
  );
};

export default Button;
export { Button };
import React from 'react';
import {
  Text,
  View
} from 'react-native';
import { Button } from 'components';
import style from './style';

const Comp1 = (props) => {
  const {
    textStyle,
    viewStyle
  } = style;

  return (
    <View style={viewStyle}>
      <Text style={textStyle}>some text</Text>
      <Button>Test</Button>
    </View>
  );
};

export default Comp1;
export { Comp1 };

运行此安装程序会产生eslint错误。代码本身是有效的

如果我将
src/components/comp1/index.jsx中的
import{Button}从'components'
中的'components'
更改为
import{Button}从'components/Button'
中,则不会弹出任何eslint错误

我希望使用上面描述的这种简短的导入语法,而不会失去使用彼此内部模块的可能性。有办法吗?

您的结构正在
组件/index.jsx
comp1/index.jsx
之间建立循环依赖关系(以及其他具有相同功能的组件)
comp1/index.jsx
组件/index.jsx
导入,后者从
comp1/index.jsx
导入

实际本机ESMª模块与CJS²或类似模块之间的循环运行时处理不同。两者都需要小心处理循环,但它们的行为方式略有不同。如果您在捆绑机或类似设备中将ESM传输到CJS,这可能会特别令人困惑

当两个模块之间存在循环依赖关系时(为了保持简单),这意味着在某一点上,两个模块中的一个将在另一个模块之前运行,这意味着它从另一个模块获取的任何导入将要么未初始化(ESM),要么尚未定义(CJS)。因此,两个模块中的一个模块中的顶级代码不能依赖现有的导入。在ESM中,尝试使用未初始化的导出会引发错误;在CJS中,导出的值只是
未定义的

在您的示例中,我不认为这是一个问题,因为循环中模块中的顶级代码不使用从循环中其他模块的导入,它只用于稍后调用的函数(
comp1/index.jsx
使用
按钮
,但仅在调用
comp1
时使用,并且在顶级代码中不调用它。(过程可能比这更复杂,但是…)

如果代码经过测试并正常工作,您可以使用禁用组件文件的该规则(如果它允许您这样做的话)。这样,您就可以在出现实际问题的周期时全局启用该规则,但不必担心这些您已经测试过且知道是好的周期


➣ESM=ECMASScriptModules,真正的本机JavaScript模块,如果您只使用
import
export
声明(而不是
import()
动态导入),则可以对其进行静态分析


²CJS=CommonJS,一种使用
require
导出
对象的动态模块结构。

此代码的运行时结构是什么?您是传输到CommonJS(例如,
require
调用),还是离开ESM(
导入
导出
声明)在浏览器看到的传输结果中?尝试使用检查此类错误,非常有用。@T.J.Crowder老实说,我不知道CJS或ESM是否在react原生项目中生成。我只知道babel在这里用于传输代码。“babel[…]主要用于将ECMAScript 2015+代码转换为向后兼容的JavaScript版本”(请参阅)。@T.J.Crowder告诉我,这是当前实现的react本机应用程序中使用的​ECMAScript如中所示​. 这是否自动意味着我们在这里谈论ESM?有人知道吗?我知道JavaScriptCore支持ESM,但这并不一定意味着React-Native正在使用它,特别是因为React-Native早于JavaScriptCore对ESM的支持。(对不起,还没有使用React-Native。)我希望能够查看实际传输的.js文件,以了解它们使用的模块语法…我现在已经知道了。可能。要能够从“./button”导出一个像
export*这样的模块;
它需要被导入,这是在这里自动完成的。还没有考虑过这种方式。像这样,它会不断循环。但是nyway,这里唯一的解决方案是扔掉包含所有导出的
index.jsx
,并使用导入语句,如从“components/Comp1”导入{Comp1};
?@iwanuschka-不一定。我正在编辑答案,正如您所评论的那样。:-)但是如何在整个项目中禁用此规则?@theprogrammer-我假设您可以像其他任何规则一样在中禁用它。@theprogrammer-Me也可以。我想它可能是
导入/无循环