反应项目中的ES6循环依赖项

时间:2019-06-27 14:51:27

标签: javascript reactjs ecmascript-6

我刚刚使用react native建立了一个小测试项目。这对我来说是全新的(包括ECMAScript 6)。 Eslint告诉我一些有关“循环依赖项”的信息,我不知道该如何解决这个问题。该代码仍然可以正常工作。

我的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 };

src/components/comp1/index.jsx

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 };

运行此设置会产生错误es import/no-cycle。代码本身有效。

如果我将import { Button } from 'components'中的src/components/comp1/index.jsx更改为import { Button } from 'components/button',则会弹出no eslint错误。

我想使用如上所述的这种简短的导入语法,而又不会降低在彼此内部使用模块的可能性。有办法吗?

1 个答案:

答案 0 :(得分:2)

您的结构 components/index.jsxcomp1/index.jsx(以及您拥有相同事物的其他对象)之间建立循环依赖关系。 comp1/index.jsxcomponents/index.jsx导入,而comp1/index.jsxexports导入。

对于实际的ESM¹模块而言,这不是问题,但是如果将它们转译为CJS²或类似代码,则需要格外小心(因此有规则)。因此,该规则警告您。

这并不意味着您无法使用CJS做到这一点,仅意味着(再次)您需要格外小心。 CJS通过动态填充的comp1/index.jsx对象工作。当两个模块之间存在循环依赖关系(为简单起见)时,这意味着两个模块中的一个将在另一个模块之前运行,这意味着尚未定义从另一个模块导入的任何内容。因此,两个模块之一中的顶级代码不能依赖现有的导入。

在您的示例中,我不希望这是一个问题,因为循环中模块中的顶级代码未使用循环中其他模块的导入,因此仅在称为之后(Button使用Comp1,但只有在被调用时才使用import,并且在顶层代码中不会调用它。(该过程可能会更加复杂除此之外,但是...)

如果代码已经过测试并且可以正常工作,则可以使用configuration comments对组件文件禁用该规则(如果允许的话)。这样一来,您就可以在实际问题循环的情况下全局地保留规则,而不必为测试和知道的循环感到烦恼。


¹ESM = E CMA S cript M odles,真正的原生JavaScript模块,如果仅使用{{1 }}和export声明(不是import()动态导入)。

²CJS = C ommon JS ,一种使用requireexports对象的动态模块结构。

相关问题