使用渲染道具创建切换按钮以显示/隐藏子组件的问题

时间:2019-02-15 00:27:24

标签: javascript html reactjs

在原始HTML下方使用我想基于切换单击来显示/隐藏几个子组件。我遇到的问题是EditToggle链接需要显示在h2旁边(“字幕容器”内部),但是这两个组件需要在下面显示(“字幕容器”外部)。

在“建议的组件”上使用EditToggle时,我必须将两个组件放在render函数中,以便它们可以看到编辑值。这是行不通的,因为它们现在在“字幕容器” div中进行渲染。如何修改这些组件,以便可以将EditToggle用作渲染道具,但仍在html中的“字幕容器”之外渲染两个子组件?

可选注释:原始节HTML在未显示的较大父组件上重复了很多次。鉴于此,这就是我使用渲染道具将控制切换的状态提取到其自身组件中的原因之一。

此外,EditComponent中的保存将返回ReadOnlyComponent,但这里没有显示Edit / Read的内部工作原理,因为它们不是问题。

谢谢!

原始HTML

<div class="section" id="section-one">
  <div class="subtitle-container">
    <h2 class="subtitle">Title</h2>
    <a href="">Toggle</a>
  </div>
  <!-- ReadOnlyComponent -->
  <!-- EditComponent -->
</div>

建议的React组件

export class SectionComponent extends React.Component<Props> {
  render() {
    return (
      <div class="section" id="section-one">
        <div className="subtitle-container">
          <h2 className="subtitle">Title</h2>
            <EditToggle
              render={(editing) => {
              return (
                <React.Fragment>
                  {editing ? <ReadOnlyComponent /> : EditComponent }
                </React.Fragment>
              )
            }}
          />
        </div>
      </div>
    );
  }
}

使用渲染道具的拟议切换链接组件

export class EditToggle extends React.Component<Props> {
  constructor(props) {
    super(props);
  }

  state = {
    editing: false,
  };

  onToggle = () => {
    this.setState({
        editing: !this.state.editing,
    });
  }

  render() {
    return (
      <div>
        <a onClick={this.onToggle}></a>
        {this.props.render(this.state.editing)}
      </div>
    );
  }
}

1 个答案:

答案 0 :(得分:1)

我认为,这里的基本思想是门户网站https://reactjs.org/docs/portals.html

所以我们可以做的是:

export class SectionComponent extends React.Component<Props> {
  render() {
    return (
      <div class="section" id="section-one">
        <div className="subtitle-container">
          <h2 className="subtitle">Title</h2>
            <EditToggle
              portalEl={this.portal}
              render={(editing) => {
              return (
                <React.Fragment>
                  {editing ? <ReadOnlyComponent /> : EditComponent }
                </React.Fragment>
              )
            }}
          />
        </div>
        <div ref={(ref)=> this.portal=ref}></div>
      </div>
    );
  }
}

export class EditToggle extends React.Component<Props> {
  constructor(props) {
    super(props);
  }

  state = {
    editing: false,
  };

  onToggle = () => {
    this.setState({
        editing: !this.state.editing,
    });
  }
  renderPortal(){
    if(this.props.portalEl){
        return ReactDom.createPortal(this.props.render(this.state.editing), this.props.portalEl)
    }
  }
  render() {
    return (
      <div>
        <a onClick={this.onToggle}></a>
        {this.renderPortal()}
      </div>
    );
  }
}