[React]:通过 this.props.children 渲染总是卸载和装载所有子项而不是仅仅重新渲染

[React]: rendering through this.props.children always unmounts and mounts all children instead of just re-rendering

我在 React 中创建了一个具有展开折叠功能的手风琴。 渲染:

<div>
    <div>
        <label className="label">
            { this.props.label }
        </label>
    </div>
    <div style={{ display: !!this.state.expanded ? "block" : "none" }}>
{ this.props.children } </div>
</div>

我这样称呼它:

<Accordion>
    <MyComponent1/>
    <MyComponent2/>
    <MyComponent3/>
</Accordion>

但每次展开/折叠手风琴时,子组件都会被卸载。正因为如此,他们失去了自己的任何 data/state,我必须把所有东西都放在里面 也不会在发生展开折叠时重新渲染。

发生折叠展开时,子组件不应该只是重新渲染而不是卸载和再次安装。有没有办法达到同样的目的。 我不想保留每个子组件的状态

@Drew Schuster:整个代码-

导出 class 手风琴扩展 React.Component {

constructor(props) {
    super(props);
    this.state = {
        expanded: false
    }
}

public render(): JSX.Element {
    let className = My_String_Util.format("chevron-", this.state.expanded ? "down" : "right");
    return (
        <div>
            <div onClick={ this._toggle }>
                <label className={ className }  />
                <label className="label"> { this.props.label } </label>
            </div>
            <If condition={ this.state.expanded }>
                <div style={{
                    display: !!this.state.expanded ? "block" : "none"
                }}>{ this.props.children }</div>
            </If>
        </div>
    );
}

private _toggle = (): void => {
    this.setState({
        expanded: !this.state.expanded
    });
}

}

父组件:

render(): JSX.Element {
    <Accordion label="Sample Accordion2" expanded={true} >
        <MyChildComponent
                        sampleProp={"aa"}
                        stringParentProp={"initial string"}/>
                    <label>"Hello World3"</label>

                    </Accordion>
}

我的子组件:

constructor(props) {
this.state = {
stateString = this.props.stringParentProp
}
}
render(): JSX.Element {
<div onClick={this._changeLabel}>
    <label>this.state.stateString</label>
</div>
}

private _changeLabel() {
this.setState = {
stateString = this.state.stateString + "x";
}
}

每次我们点击子组件到它的标签时,这应该添加 'x'。哪个有效。但是当我们折叠然后再次展开时,标签会重置为 "initial string"

包含的代码有一些错误,导致无法编译。我删除了一些不需要重现此错误的代码,现在在此 codepen 上有了一个可行的解决方案。代码也包含在下面,我使用 React.createClass 而不是扩展 React.Component 但你当然不必这样做。:

const Accordion = React.createClass({
  getInitialState: function () {
    return { expanded: false }
  },

  _toggle: function () {
      this.setState({
          expanded: !this.state.expanded
      });
  },
  render: function () {
    return (
        <div>
            <div onClick={ this._toggle }>
                <label className={ className }  />
                <label className="label"> { this.props.label } </label>
            </div>
            <div style={{
                display: !!this.state.expanded ? "block" : "none"
              }}>{ this.props.children }</div>
        </div>
    );
  }
});

const MyChildComponent = React.createClass({
  getInitialState: function () {
    return { stateString: this.props.stringParentProp}
  },
  _changeLabel: function () {
    this.setState(
      {
      stateString: this.state.stateString + "x"
    })
  },
  render: function () {
    return (
      <div onClick={this._changeLabel}>
        <label>{this.state.stateString}</label>
      </div>
    )
  }
})

const Parent = () => {
    return (
      <Accordion label="Sample Accordion2" expanded={true} >
          <MyChildComponent
            sampleProp="aa"
            stringParentProp="initial string"/>
          <label>"Hello World3"</label>
      </Accordion>
    )
}


ReactDOM.render(<Parent/>, document.getElementById('container'))