如何将父组件的子组件包装在 HOC 中并在 React 中呈现它们?

How can I wrap the Children of a Parent component in a HOC and render them in React?

先说这个例子很简单,用React.cloneElement就可以解决。但是我想要更多的自由,项目会更复杂,所以我想找到一个解决方案。
我也想了解我所缺少的东西:/

我希望能够使用 props 和方法(因此是 HOC)来扩充父组件的子组件。它将从这里开始:

<Parent>
  <aChild />
  <anotherChild />
  <yetAnotherChild />
</Parent>

这是父组件(在我的项目中称为 Sequence),到目前为止:

import React, { Component } from 'react';

const withNotification = handler => Component => props => (
  <Component onAnimationEnd={handler} {...props} />
);

class Sequence extends Component {
  constructor(props) {
    super(props);

    this.state = {
      pointer: 0,
    };

    this.notifyAnimationEnd = this.notifyAnimationEnd.bind(this);

    this.Children = React.Children.map(this.props.children, Child =>
      withNotification(this.notifyAnimationEnd)(Child)
    );
  }

  notifyAnimationEnd() {
    // do stuff
  }

  render() {
    return (
      <div>
        {this.Children.map((Child, i) => {
          if (i <= this.state.pointer) return <Child />;
          return <div>nope</div>;
        })}
      </div>
    );
  }
}

export default Sequence;

我收到以下错误:

你可以在这里玩代码:https://codesandbox.io/s/6w1n5wor9w

感谢您的帮助!

您在 Sequence.js 渲染方法中返回 <Child /> 而不是 Child。这是我编辑过的副本 - codesandbox

这个答案不会解决您的问题,但可能会提示为什么这是不可能的。起初我很惊讶为什么你的代码不起作用,即使我不是经验丰富的 React 开发人员,它似乎可以通过 React.Children.map 和 return 映射 this.props.children 所需的组件与你的 HOC .但它没有用。

我试着稍微调试了一下 did some search。我了解到 props.children 实际上包含元素本身而不是组件的实例。 即使 React.Children.map 对此没有任何影响。

这是一个工作片段,证明您的问题与 HOC 无关。我使用了一组组件而不是通过 props.children.

进行映射

class Line1 extends React.Component {
  componentDidMount() {
    setTimeout(this.props.onAnimationEnd, 1000);
  }

  render() {
    return <div>Line 1</div>;
  }
}

class Line2 extends React.Component {
  componentDidMount() {
    setTimeout(this.props.onAnimationEnd, 1000);
  }

  render() {
    return <div>Line 2</div>;
  }
}

class Line3 extends React.Component {
  componentDidMount() {
    setTimeout(this.props.onAnimationEnd, 1000);
  }

  render() {
    return <div>Line 3</div>;
  }
}


const withNotification = handler => Component => props => (
  <Component onAnimationEnd={handler} {...props} />
);

class Sequence extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      pointer: 0
    };

    this.notifyAnimationEnd = this.notifyAnimationEnd.bind(this);

    this.Arr = [ Line1, Line2, Line3 ];
    this.Children = this.Arr.map(Child =>
      withNotification(this.notifyAnimationEnd)(Child)
    );
  }

  notifyAnimationEnd() {
    this.next();
  }

  next() {
    // Clearly, render the next element only if there is, a next element
    if (this.state.pointer >= this.Arr.length - 1) {
      return;
    }

    this.setState({ pointer: this.state.pointer + 1 });
  }

  render() {
    return (
      <div>
        {this.Children.map((Child, i) => {
          if (i <= this.state.pointer) return <Child />;
          return <div>nope</div>;
        })}
      </div>
    );
  }
}



ReactDOM.render(
  <Sequence />,
  document.getElementById("app")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>