有没有办法判断 ReactElement 是否呈现 "null"?

Is there a way to tell if ReactElement renders "null"?

在我的 JSX 中,我有一个条件渲染逻辑的情况 - 当元素 A 渲染某些东西(它是 render() 函数 returns 除了 null 之外的东西),然后也渲染元素 B,就在元素 A 的上方。

代码示例(简化)如下所示:

function render() {
    let elemA = (<ElementA someProp={this.someVar} />);

    if (elemA.isNull()) {
        return (
            <div>
                { ...someElements }
            </div>
        );
    }

    return (
        <div>
            { ...someElements }
            <ElementB />
            { elemA }
        </div>
    );
}

所以我的问题是 - 有什么方法可以让 elemA.isNull() 检查吗?

不,无法确定 child 使用 React 将呈现什么。执行此操作的标准方法是公开一些实用函数,说明 A 是否将呈现。

类似于:

if (AUtils.isStoryValid(story)) {
  return <A story={story} />;
} else {
  return <B story={story} />;
}

你可以使用下面的高阶组件(HOC)来拦截ElementA的render方法,完成你想要的:

function withNullCheck(WrappedComponent) {
  return class NullChecker extends WrappedComponent {
    render() {
      const result = super.render();
      return(
        <div>
          { this.props.alwaysPrefix }
          { result && this.props.ifNotNullPrefix }
          { result ? result : this.props.ifNull }
          { result && this.props.ifNotNullAppend }
          { this.props.alwaysAppend }
        </div>  
      );
    }
  }
}

你会像这样使用它:

const NullCheckedElementA = withNullCheck(ElementA);

...

function render() {

    return ( 
      <NullCheckedElementA 
         alwaysPrefix={someElements} 
         ifNotNullPrefix={elemB} 
         someProp={this.someVar} 
      />
    );

}

所以我 运行 陷入了不得不这样做的境地,这是一种可行的方法(尽管骇人听闻可能会让您哭泣)。

只应作为最后的手段使用,因为它确实是一个彻头彻尾的黑客攻击,根据组件的复杂性,您将遭受大约 0-20 毫秒的性能损失。 (假设您正在使用 redux 并且您的组件取决于您的 redux 状态,提供程序就在那里):

import { renderToStaticMarkup } from 'react-dom/server';
import { Provider } from 'react-redux';
import store from 'pathToYourReduxStoreInstance';


export default function isRenderingNull(componentInstance) {
  return !renderToStaticMarkup(
    <Provider store={store}>
      {componentInstance}
    </Provider>
  )
}

请注意,如果您的 ReactElement 已被编写为功能组件,您可以像调用任何其他函数一样调用该函数并检查其响应。 作为一个简单的例子,我有一个函数组件,它 returns 基于传入的道具的不同图标:

import React from "react";

import PersonIcon from "@material-ui/icons/Person";
import GroupIcon from "@material-ui/icons/People";

export default function EntityIcon({ entity }) {
  switch (entity) {
    case "people":
      return <PersonIcon />;
    case "groups":
      return <GroupIcon />;
    default:
      console.error(`entity: ${entity} doesn't have an associated icon`);
      return null;
  }
}

以上通常引用:

    <ListItemIcon>
      <EntityIcon entity={search.entity} />
    </ListItemIcon>

但如果需要,我可以使用一些条件魔法:

  if (EntityIcon({ entity: item.entity })) {
    ... conditional magic
  }
在我的用例中,

search.entityitem.entity 恰好是对象数组的属性,但我希望你能理解。

如果你的ElementA是函数组件就容易了。在这种情况下,您可以像这样执行 smt:

    function render() {
    let ElemA = ElementA({ someProp:  this.someVar});

    if (ElemA === null) {
        return (
            <div>
                { ...someElements }
            </div>
        );
    }

    return (
        <div>
            { ...someElements }
            <ElementB />
            <ElemA />
        </div>
    );
}