如何使用React + ES6 + webpack导入和导出组件?

154

我正在使用 babelwebpack,尝试着用 ReactES6 制作一些组件。我希望将这些不同的组件放在不同的文件中,然后在一个文件中引入它们,并用 webpack 打包起来。

假设我有几个像这样的组件:

my-navbar.jsx

import React from 'react';
import Navbar from 'react-bootstrap/lib/Navbar';

export class MyNavbar extends React.Component {
    render(){
      return (
        <Navbar className="navbar-dark" fluid>
        ...
        </Navbar>
      );
    }
}

main-page.jsx

import React from 'react';
import ReactDOM from 'react-dom';

import MyNavbar from './comp/my-navbar.jsx';

export class MyPage extends React.Component{
  render(){
    return(
        <MyNavbar />
        ...
    );
  }
}

ReactDOM.render(
  <MyPage />,
  document.getElementById('container')
);

我使用webpack并按照他们的教程,现在我有了main.js文件:

import MyPage from './main-page.jsx';

在构建项目并运行后,我在浏览器控制台中看到了以下错误:

Error: Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. Check the render method of `MyPage`.

我做错了什么?我该如何正确地导入和导出组件?


export 关键字的详细信息请参见此处。目前,它在任何 Web 浏览器中都没有本地支持。 - RBT
6个回答

142

尝试在您的组件中默认导出:

import React from 'react';
import Navbar from 'react-bootstrap/lib/Navbar';

export default class MyNavbar extends React.Component {
    render(){
      return (
        <Navbar className="navbar-dark" fluid>
        ...
        </Navbar>
      );
    }
}

使用 default 关键字可以表示你要导入该模块的成员,如果没有提供特定的成员名称。例如:如果在代码中没有指定具体的成员名称,那么导入的就是默认成员。如果你想导入名为 MyNavbar 的特定成员,可以这样做:import {MyNavbar} from './comp/my-navbar.jsx'; 在这种情况下,不需要使用 default 关键字。


这对我没用。在我的项目中运行它时,我收到错误消息,说它无法导入该组件。任何想法为什么? - BHouwens
6
使用默认选项,表示该成员将成为导入模块时提供的未指定具体成员名称的成员。您还可以通过以下方式表示要导入名为MyNavbar的特定成员:import {MyNavbar} from './comp/my-navbar.jsx'; 在这种情况下,不需要使用默认选项。 - Emilio Rodriguez

108

如果没有默认导出,使用大括号包装组件:

import {MyNavbar} from './comp/my-navbar.jsx';

或从单个模块文件中导入多个组件

import {MyNavbar1, MyNavbar2} from './module';

5
这应该是正确的答案。这些是ES6中的“命名导出”,是一种比使用“默认导出”更安全的导出方式。https://developer.mozilla.org/en/docs/web/javascript/reference/statements/export - kaushik94
用大括号包裹组件如果没有默认导出就可以了。谢谢。 - EugenSunic
1
也许这可以帮助:在我的情况下,路径中缺少'./'。这听起来有点奇怪,因为组件位于同一文件夹级别。 - Alessandro De Simone

105

要在ES6中导出单个组件,您可以使用以下的export default

class MyClass extends Component {
 ...
}

export default MyClass;

现在您可以使用以下语法导入该模块:

import MyClass from './MyClass.react'

如果您想要从单个文件中导出多个组件,则声明会类似于以下内容:

export class MyClass1 extends Component {
 ...
}

export class MyClass2 extends Component {
 ...
}

现在,您可以使用以下语法导入这些文件:

import {MyClass1, MyClass2} from './MyClass.react'

10

MDN有非常好的文档,介绍了在ES6中导入和导出模块的新方法Import-MDN。对于你的问题,以下是简要说明:

  1. 声明你要导出的组件为本模块的“默认”组件:export default class MyNavbar extends React.Component {,这样当导入'MyNavbar'时,你就不必在它周围加上大括号:import MyNavbar from './comp/my-navbar.jsx';。但是,如果没有将此组件声明为“默认导出”,那么不在导入周围放置大括号会导致错误(正如你所遇到的问题)。

  2. 如果不想在导出时将'MyNavbar'声明为默认导出:export class MyNavbar extends React.Component {,那么你需要使用大括号来包裹'MyNavbar'的导入:import {MyNavbar} from './comp/my-navbar.jsx';

我认为,由于你的'./comp/my-navbar.jsx'文件中只有一个组件,因此将其设置为默认导出很方便。如果你有更多的组件,如MyNavbar1,MyNavbar2,MyNavbar3,则不应将它们中的任何一个设为默认值。如果模块没有声明任何默认选项,你可以使用import {foo, bar} from "my-module";来导入模块的选定组件,其中foo和bar是模块中的多个成员。

一定要阅读MDN文档,它提供了语法的良好示例。希望这有助于为任何想要在React中玩耍ES6和组件导入/导出的人提供更详细的说明。


5

希望这对您有所帮助。

步骤1:App.js 是(主模块),导入登录模块。

import React, { Component } from 'react';
import './App.css';
import Login from './login/login';

class App extends Component {
  render() {
    return (
      <Login />
    );
  }
}

export default App;

步骤2:创建登录文件夹,并创建login.js文件并按照您的需求进行自定义,它将自动呈现到App.js。例如:Login.js。
import React, { Component } from 'react';
import '../login/login.css';

class Login extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default Login;

3

在React中,有两种不同的导入组件的方式,推荐使用组件方式。

  1. 库方式(不推荐)
  2. 组件方式(推荐)

以下是详细解释:

库方式导入

import { Button } from 'react-bootstrap';
import { FlatButton } from 'material-ui';

这很方便实用,但它不仅捆绑了Button和FlatButton(以及它们的依赖项),而是整个库。
组件化导入的方法:
缓解这种情况的一种方式是尝试仅导入或需要的内容,也就是说,使用组件化导入的方式。 使用相同的示例:
import Button from 'react-bootstrap/lib/Button';
import FlatButton from 'material-ui/lib/flat-button';

这将仅捆绑Button、FlatButton及其各自的依赖项,而不是整个库。因此,我建议尝试摆脱所有库导入,并改用组件方式。如果您没有使用很多组件,则应该显著减少捆绑文件的大小。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接