如何在HOC中包装Parent组件的Children并在React中呈现它们?

问题描述 投票:2回答:2

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

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

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

到目前为止,这是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;

我收到以下错误:

React Error

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

感谢您的任何帮助!

javascript reactjs higher-order-components
2个回答
1
投票

这个答案不会解决你的问题,但可能会暗示为什么这是不可能的。起初我很惊讶为什么你的代码不起作用,即使我不是一个经验丰富的React开发人员,似乎可以通过this.props.children映射React.Children.map并使用你的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>

0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.