[英]ES6 circular dependency in react project
我刚刚使用 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 };
运行此设置会产生 eslint 错误import/no-cycle 。 代码本身有效。
如果我将src/components/comp1/index.jsx
import { Button } from 'components'
更改为import { Button } from 'components/button'
,则会弹出 no eslint 错误。
我想使用上面描述的这种简短的导入语法,而不会失去在彼此内部使用模块的可能性。 有办法吗?
您的结构设置之间的循环依赖components/index.jsx
和comp1/index.jsx
(和其他人,你有同样的事情)。 comp1/index.jsx
从components/index.jsx
导入,它从comp1/index.jsx
导入。
实际的原生 ESM¹ 模块和 CJS² 或类似模块之间的循环运行时处理是不同的。 两者都需要仔细处理循环,但它们的行为方式略有不同。 如果您在打包器或类似工具中将 ESM 转换为 CJS,这可能会特别令人困惑。
当两个模块之间存在循环依赖时(为简单起见),这意味着在某个时刻,两个模块中的一个将在另一个模块之前运行,这意味着它从另一个模块获取的任何导入都将未初始化(ESM)或尚未初始化被定义(CJS)。 因此,两个模块之一中的顶级代码还不能依赖于现有的导入。 在 ESM 中,尝试使用未初始化的导出会引发错误; 在 CJS 中,导出的值只是undefined
。
在您的示例中,我不希望这是一个问题,因为循环中模块中的顶级代码不使用循环中其他模块的导入,它仅用于稍后调用的函数中( comp1/index.jsx
使用了Button
,但只在调用Comp1
时,在顶层代码中不会调用。(过程可能比那更复杂,但是...)
如果代码经过测试并且可以工作,您可以使用配置注释来禁用组件文件的该规则(如果它允许您这样做)。 这使您可以在实际出现问题的循环的情况下将规则保留在全局范围内,但不会为这些您已经测试并知道是好的循环而烦恼。
¹ESM = E CMA小号CRIPT中号odules,真正原生的JavaScript模块,如果你只使用其中的静态分析的import
和export
报关单(不import()
动态的进口)。
² CJS = C ommon JS ,一个使用require
和一个exports
对象的动态模块结构。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.