尽管在 defaultProps 中设置了 children 道具,但为什么它仍未定义?

Why is children prop undefined, despite setting it in defaultProps?

我想为我的 React 组件设置 PropTypes 验证,以便在没有子组件时发出警告。但是当我遵循 PropTypes 语法 recommended by the React docs 时,我抛出了这个错误:

prop type children is invalid; it must be a function, usually from the prop-types package, but received undefined.

当我在 Chrome 调试器中单步执行时,我看到 children 在执行验证时是 undefined。但是我特意在defaultProps里设置了children,为什么是undefined呢?我为 defaultProps.children 尝试了几个不同的值,包括 []''。他们都产生了同样的错误。

请注意,我的应用运行正常。只有 PropTypes 验证失败。

下面是有问题的代码的简化版本。请注意,我使用静态属性来定义 defaultProps(如 recommended by Dan Abramaov)。我正在使用 create-react-app 所以我有 Babel 转换来启用默认的 class 属性语法。

import React, { Fragment } from 'react';
import PropTypes from 'prop-types'
import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import classnames from 'classnames';

export class Tab extends React.Component {

  static propTypes = {
    name: PropTypes.string.isRequired,
    children: PropTypes.node.required,
  }

  static defaultProps = {
    name: null,
    children: ''
  }

  render () { 
    return (
      <Fragment>
        {this.props.children}
      </Fragment>
    )
  }
}

export default class TabSet extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      activeTab: 0
    };
  }

  // TODO: limit to only Tab child elements. 
  static propTypes = {
    children: PropTypes.node.required,
  }

  static defaultProps = {
    children: ''
  }

  toggle = (tab) => {
    if (this.state.activeTab !== tab) {
      this.setState({
        activeTab: tab
      });
    }
  }

  render() { 
    return (
      <Fragment>
        <Nav tabs>
          {this.props.children.map((tab,i) => 
            <NavItem key={i} style={{cursor: 'pointer'}}>
              <NavLink
                className={classnames({ active: this.state.activeTab === i })}
                onClick={() => { this.toggle(i); }}
              >
                { tab.props.name }
              </NavLink>
            </NavItem>
          )}
        </Nav>
        <TabContent activeTab={this.state.activeTab}>
          {this.props.children.map((tab,i) => 
            <TabPane key={i} tabId={i}>
              {tab}
            </TabPane>
          )}
        </TabContent>
      </Fragment>
    );
  }
}

如果重要,这里有一个关于如何使用这些组件的简化示例:

import React from 'react';
import TabSet, {Tab} from './TabSet';
import HomeTab from './HomeTab';
import FriendsTab from './FriendsTab';
import HangTimesTab from './HangTimesTab';

export default class MainContainer extends React.Component {

  render() {
    return (
      <div>
        <TabSet>
          <Tab name="Home">
            <HomeTab /> 
          </Tab>
          <Tab name="Hang Times">
            <HangTimesTab />
          </Tab>
          <Tab name="Friends">
            <FriendsTab />
          </Tab>
        </TabSet>
      </div>
    );
  }
}

错误消息有点混乱,但它指的是 children 的 prop-type 声明(即 PropTypes.node.required),这是 undefined 因为打字错误.应该是 PropTypes.node.isRequired.