Why do you need to import React multiple times in

2019-03-12 16:08发布

问题:

If you have a parent component file that already imports React, why does any of its rendered children files also need to import React? Is it just a safety measure in case those children are ever rendered somewhere else where React has not been imported yet?

回答1:

In nodejs each file is a module, that has its own scope of variables. When you import variable into file (React for example) you add this variable to the module scope, but not to the global scope.

In case of webpack you can use providePlugin to easily make React variable global:

new webpack.ProvidePlugin({
  React: 'react' // ReactJS module name in node_modules folder
})

After that you are able to skip importing React variable in all of your modules. Webpack will do it itself where needed.



回答2:

If you use JSX and babel, you have to import React in every file because babel-preset-react will transpile your JSX code into React.createElement() calls, so this code

const Foo = () => <h1>Test</h1>;

will be

var Foo = function Foo() {
  return React.createElement(
    "h1",
    null,
    "Test"
  );
};

DEMO: Babel REPL

This is the reason why React should be accessible in the proper scope and one way to do it, is to import React in a file.



回答3:

The root of the question is one of dependency management -- how do I, the author, describe and obtain external dependencies I need in my "thing" (application/component/module) for it to do its job?

JavaScript benefits (or suffers) from having a global namespace in which dependencies can be injected. While this can often simplify dependency management in the short term (e.g. you can ignore it and expect everything you need to be available in the global namespace), it can often cause issues as an application grows and changes. For example, given an application with multiple contributors, one might decide to change a part of the application to no longer use a particular dependency and therefore remove it. If another part of the application needed it but that dependency wasn't formally declared anywhere, it could be easily missed.

To do dependency management well, each discrete "thing" should describe its dependencies independent of any other "thing" such that it can be safely used in any given context. This ensures that each "thing" has exactly what it needs no matter how it is used and what its "parent" (the code importing the "thing") has.

An alternative to this approach is dependency injection. In this model, the "thing" provides an interface for passing the dependencies into the "thing" from the consumer. There are flexibility and testability advantages to this which are out of scope of your question. :)

// export a function that expects the React and PropTypes
// dependencies to be injected as parameters and returns
// the component rather than importing the dependencies
// and exporting the component
export default (React, PropTypes) => {
  return class extends React.Component {
    static propTypes = {
      name: PropTypes.string.isRequired
    }
    render () {
      return (
        <div />
      );
    }
  };
};

All of that to say, it is somewhat a "safety measure" to have each "thing" import its own dependencies. It lets you safely refactor your code without the cognitive overhead of remembering what is providing those dependencies.



回答4:

The reason is to avoid unnecessary compiled a JavaScript code that you don't have to compile jsx. For example, you have a file that have a function to do adding, or whatever function that doesn't need to compile jsx, then you don't put import React from 'react' on the top of that file. This will save you compile time.