2017-10-31 7 views
0

I以下のモジュールの構造を有する:インポートされたモジュールに、「循環」依存関係を持つファイルの最上位レベルのスコープにアクセスしますか?

/components 
├── Button.js 
├── Checkbox.js 
├── index.js 
├── DateSelect 
   ├── DateSelect.js 
   └── index.js 

/components/DateSelect/index.js付:

import DateSelect from './DateSelect'; 

export default DateSelect; 

/components/index.js

import DateSelect from './DateSelect'; 
import Button from './Button'; 
import Checkbox from './Checkbox'; 

export { 
    DateSelect, 
    Button, 
    Checkbox, 
}; 

そして/components/DateSelect/DateSelect.js

import { Checkbox } from '../'; 
// ...code 

// I want to do this! 
const MyCustomCheckbox = props => <Checkbox style={someStyle} />; 

// ...code 
class DateSelect extends React.Component { 
    // code 
} 
export default DateSelect; 

ここでは、上記のコードのようにファイルの最上位レベルのCheckboxにアクセスしたいと思いますが、undefinedとなります。しかし、私がこの変数にアクセスすると、DateSelectrenderメソッドでは、期待どおりに動作します。

私はこれがどういう場合であるか、またはこれを修正する方法について完全にはわかりません(import Checkbox from '../Checkbox'を実行できますが、ディレクトリのindex.jsファイルを使用するパターンを変更したくありません)。私はまた、何が起こっているのか正確に理解したい。何か案は?

+0

なぜ 'Checkbox.js'はDateselect.js''に依存していますか?あなたはそのコードを投稿できますか? – Bergi

+0

@Bergi @Bergi確かに、私のコンピュータにアクセスするのに数分を要しますが、チェックボックスはDateSelectに依存しません。私が話した循環依存性はDateSelect.jsとcomponents/index.jsの間であり、 – YoTengoUnLCD

+1

さて、それは順番に 'Checkbox'をインポートされた' Dateselect'に依存させます。 [そのような循環参照を避ける](https://stackoverflow.com/a/46593566/1048572)! 'Button'モジュールを直接インポートするだけです。 – Bergi

答えて

1

お客様の問題は、輸出に循環的な依存関係があることです。/components/index.jsです。

ビルド・ツールは、最初のアプリケーションを構築するとき、それはありません、次の...輸出を宣言しcomponents/index.jscomponents/index.js

  • 行くからDateSelectをインポート

    • 始まると言う、で、app.js

      // SPOILER: This guy is your problem. We'll call him the douche. 
      export { 
          DateSelect, 
          Button, 
          Checkbox, 
      }; 
      
    • ダッシュが宣言されるためには、components/DateSelect.jsからのものをインポートする必要があります。 components/Button.jscomponents/Checkbox.js

    • は、これらのファイルに行くとすぐそれがDateSelectを構築するために行くようにそれらに
    • で何構築を開始し、すでにcomponents/index.jsで潅水を知っているcomponents/index.js
    • からCheckBoxをインポートするように言われていますので、潅水にCheckBoxを探して行く(それそれに戻って「丸」)が、それはundefined
    を返すようCheckBoxは、まだcomponents/CheckBox.jsで宣言されていません

    これはタイミングの問題です。 CheckBoxは、インポートしようと数回クリックすると定義されますが、ビルドには遅すぎます。

    あなたはすぐにCheckBoxをロギングすることで、これを表示することができますし、import文の後に数ミリ秒...だから

    // /components/DateSelect/DateSelect.js: 
    
    import { Checkbox } from '../'; 
    console.log(CheckBox); // undefined 
    setTimeout(() => console.log(CheckBox), 4) // function CheckBox(_ref) { ... 
    

    、あなたがMyCustomCheckboxを宣言しようとすると、CheckBoxは未定義です。

    DateSelectのレンダリングメソッドが呼び出された時点で、CheckBoxが宣言されています。これは、相対的に、ビルドプロセスより遅れている。

    アプリケーション構造全体に依存するため、この種の問題に対する100%安全な解決法はありません。それはあなたがcomponents/CheckBox.jsから直接インポートすることにより、バック潅水に旋回回避または1つのレベルより深いインデックス化モジュールアプローチを取ると、作成することができます潅水

    を避け戻って同じモジュールに

    を旋回避けることが最善であります少しのCheckBoxモジュール...

    /components 
        /CheckBox 
        CheckBox.js 
        index.js 
    

    ...その後import {CheckBox} from '/components/Checkbox'

  • +0

    洗面器は*物ではありません*。オブジェクトリテラルに似ていますが、エクスポートされた名前の宣言にすぎません。あなたの提案との唯一の違いは、 'export {DateSelect as DateSelect}'ではなく、 './DateSelect'から 'export {default as DateSelect} 'に相当します。 './DateSelect'; 'から。 – Bergi

    +0

    OK @ベルギーので、私はボンネットの下にドゥシェの性質を誤解した。それを編集します。しかし、doucheメソッドを使用すると、ビルドツールが元に戻ってくる安定したアイデンティティーを持つエクスポートエンティティが作成されます。したがって、個々のエクスポートステートメントを使用するアプローチが機能します。名前付きエクスポートメソッドをなぜ批判するのかも分かりません。 –

    +0

    @Bergi質問に直接応答して解決策を提示するが、技術的なエラーは小さいが、回答をダウンボートすることは適切であるか役立つか?いずれにしても、モジュール読み込みの実装は正確には透過的ではないので、この種の説明のためのオブジェクトとしての輸出はあまりにも犯罪だとは思わない。 –

    関連する問題