React 16.3.0 Context API的多个嵌套使用者

时间:2018-04-20 13:04:38

标签: reactjs

按照反应16.3.0的新上下文API,我创建了HOC,以便我的上下文更容易被许多组件使用。

但是,如果我有一个以上的组件消耗了一个接一个地嵌套的上下文,那么反应会抛出错误。

让我们说我的例子我有css模块我想传递下来,HOC看起来如下:

import React from 'react';
import CssModuleContext from './CssModuleContext';

export default function withCssModule(Component) {
  return function CssModuleComponent(props) {
    return (
      <CssModuleContext.Consumer>
        {cx => <Component {...props} cssModule={cx} />}
      </CssModuleContext.Consumer>
    );
  };
}

然后我有两个消耗此上下文的组件:

@withCssModule
export default class A extends PureComponent {
  static B = B;

  static propTypes = {
    cssModule: PropTypes.func,
  };

  render() { ... }
}

@withCssModule
export default class B extends PureComponent {
  static propTypes = {
    cssModule: PropTypes.func,
  };

  render() { ... }
}

用法如下:

render() {
  return(
    <A>
      <A.B />
    </A>
  );
}
  

React.createElement:type无效 - 期望一个字符串(for   内置组件)或类/函数(用于复合组件)   但得到了:未定义。您可能忘记从中导出组件   它定义的文件,或者你可能混淆了默认和命名   进口。

抛出错误,当我只使用其中一个组件时没有错误,但我无法嵌套它们。这是一个常见错误吗?它有解决方法吗?或者我可能做错了什么?

CssModuleContext.js

import React from 'react';

const defaultCssModule = null; // we want to use component defined module by default

const CssModuleContext = React.createContext(defaultCssModule);

export default CssModuleContext;

CssModuleProvider.js

import React from 'react';
import PropTypes from 'prop-types';
import CssModuleContext from './CssModuleContext';

export default class CssModuleProvider extends React.Component {
  static propTypes = {
    children: PropTypes.element.isRequired,
    cssModule: PropTypes.func.isRequired,
  }

  constructor(props) {
    super(props);

    const { cssModule } = this.props;

    this.state = { cssModule };
  }

  render() {
    return (
      <CssModuleContext.Provider value={this.state.cssModule}>
        {React.Children.only(this.props.children)}
      </CssModuleContext.Provider>
    );
  }
}

1 个答案:

答案 0 :(得分:2)

问题是因为我向HOC导出了那个对象无法访问的静态变量。

执行以下操作

@withCssModule
export default class A extends PureComponent {
  static B = B;

  static propTypes = {
    cssModule: PropTypes.func,
  };

  render() { ... }
}

然后尝试像<A.B />那样访问B将无效,因为我们导出包装器而不是类本身。