需要特定包含组件的反应组件的模式

Pattern for react components that require specific contained components

编写嵌套特定子组件的组件的惯用 React 方法是什么?我知道如何编写一个简单包装 props.children 的组件,就像 React 自己的文档中的这个例子:

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

但是如果我想创建一对可以像这样使用的组件怎么办:

<TabSet>
  <Tab name="Mammals">
     content for <b>warm blooded</b> creatures here
  </Tab>
  <Tab name="Fish">
     content for <b>cold blooded</b> creatures here
  </Tab>
</TabSet>

这是我对 TabSet 的初始实现(使用 reactstrap),经过简化以删除样式、选定选项卡管理以及与此问题无关的其他内容。

import React, {Fragment, Component} from 'react';
import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';

export default class TabSet extends Component {

  render(props) { 
    return (
      <Fragment>
        <Nav tabs>
          {props.children.map((tab,i) => 
            <NavItem key={i}>
              <NavLink>
                { tab.name }
              </NavLink>
            </NavItem>
          )}
        </Nav>
        <TabContent>
          {props.children.map((tab,i) => 
            <TabPane key={i} tabId={i}>
              { tab.children }
            </TabPane>
          )}
        </TabContent>
      </Fragment>
    );
  }

}

我卡住的地方是如何实现 Tab 组件。从逻辑上讲,它是 TabSet 组件的一部分——它永远不应该独立存在。它的实现应该非常简单,因为它实际上什么都不做——它只是 name 属性和子元素的容器。

所以,这里有几个问题:

很抱歉这个问题很明显——我是 React 和 ES6 的新手。

在您使用 export default class ... 的地方,您实际上可以在此处导出您自己的 object。考虑到这一点,您可以执行以下操作:

const TabSet = props => (
  <Your Tabset markup here>
)

const Tab = props => (
  <Your Tab markup here>
)

export {
  Tabset,
  Tab
}

这样做可以让您在一行中导入两个组件:

import { Tabset, Tab } from 'wherever'

虽然这是一种方法,虽然您认为 Tab 很简单,但我仍然相信它们属于自己的文件。因此,只需为 TabsetTab 创建两个 class 文件,然后创建名为 tabs.js 之类的第三个文件。它应该包含两者的 link,例如:

import Tabset from './tabset'
import Tab from './tab'

export {
  Tabset,
  Tab
}

这样您就可以为每个组件指定文件,并且可以将它们作为单个导入来导入。


此外,如果您使用反应的 PropTypes 能力,您可以限制 Tabset 的 children 实际上是您的标签。 Here 是概述,但作为示例,您可以执行以下操作:

// untested
static propTypes = {
  children: PropTypes.arrayOf(PropTypes.instanceOf(Tab))
}

您必须将 Tab 组件导入 set 组件才能执行此操作。

如果该组件仅在另一个组件的上下文中使用,则将它们放在同一个模块中是合乎逻辑的,许多库都这样做。实现此目的的方法是在不使用 default 的情况下使用多个 export 语句。您可以根据需要使用一个 export default 和任意多个 export 语句。像这样

export default class TabSet 
...
export class Tab

并导入

import TabSet, {Tab} from './Tab'

一般语法是

import defaultExport, { namedExport1, namedExport2  } from "module"

语法可能看起来有点混乱here is the reference