更新组件数组中单个React子组件的状态?

时间:2016-12-18 01:09:28

标签: reactjs

到目前为止,我有扩展/折叠所有功能,以便在单击展开/折叠所有按钮时显示/隐藏标题组件。

Container组件是最外层的组件,并保持openAll状态,该状态向下传递给Text组件作为道具。

正如您所看到的,在Container组件的render方法中,我返回一个嵌套了Button组件的div和一组title(这是一个div与Toggle和Title组件嵌套)。

我最大的问题是如何在单击Toggle组件时设置单个Title组件的状态? Title和Toggle组件都在同一级别上。我尝试过使用来自父(Container组件)的回调,但它对我不起作用。

如果你看一下Container里面的onToggle方法,我注释掉了代码,因为它会一次显示/隐藏所有的Title组件而不是一个...这是因为它在一个数组中。

Title组件具有isOpen状态,当组件收到下一个道具时,它由父道具(Container组件 - openAll)设置。

也许我过度思考这个并且比看起来更难。

初始应用组件:

class App extends React.Component {
  render() {
    return (
      <div>
        <Container text="Text" />
      </div>
    );
  }
}

容器组件:

class Container extends React.Component {
  constructor() {
    super();
    this.state = {
      openAll: true,
    };
    this.onExpandAll = this.onExpandAll.bind(this);
    this.onToggle = this.onToggle.bind(this);
  }
  render(){
    const titles = [];
    for(let i = 0; i < 3; i++){
      titles.push(
        <div key={i}>
          <Toggle text="Toggle" onToggle={this.onToggle} />
          <Title
            onToggle={this.onToggle}
            openAll={this.state.openAll}
            text={this.props.text + ' ' + i} />
        </div>
      );
    }
    return (
      <div>
        <Button text="Expand All" onExpandAll={() => this.onExpandAll(true)}  />
        <Button text="Collapse All" onExpandAll={() => this.onExpandAll(false)} />
        {titles}
      </div>
    );
  }

  onToggle() {
    //this.setState({
      //openAll: true
    //});
  }

  onExpandAll(isAllOpen) {
    this.setState({
      openAll: isAllOpen
    });
  }
}

标题组件:

class Title extends React.Component {
      constructor() {
        super();
        this.state = {
          isOpen: true
        }
      }

      componentWillReceiveProps(nextProps) {
        this.setState({
          isOpen: nextProps.openAll ? true : false
        })
      }

      render(){
        return this.state.isOpen ? <h3 style={{display: "inline-block"}}>{this.props.text}</h3> : null;
      }
    }

切换组件:

class Toggle extends React.Component {
  render(){
    return <button onClick={this.props.onToggle}>{this.props.text}</button>
  }
}

按钮组件:

class Button extends React.Component {
  render(){
    return <button onClick={this.props.onExpandAll}>{this.props.text}</button>
  }
}

HTML看起来像这样:

Expand All | Collapse All 

Toggle Text 0
Toggle Text 1
Toggle Text 2

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我建议添加另一个包含Title和Toggle组件的组件。我们称这个组件为&lt; TitleToggleContainer&gt; TitleToggleContainer将负责isOpen的状态,并将相应地有条件地呈现子Title组件。 Toggle子组件将独立于componentWillReceiveProps中对setState的更改而设置isOpen状态,因此只有其兄弟Title将受到对isOpen的本地更改的影响。 修订后的容器组件: class Container扩展了React.Component {   构造函数(道具){     超级(道具);     this.state = {       openAll:是的,     };     this.onExpandAll = this.onExpandAll.bind(this);     this.onToggle = this.onToggle.bind(this);   }   渲染(){     const titles = [];     for(let i = 0; i&lt; 3; i ++){       titles.push(         &LT; TitleToggleContainer           key = {i} //注意onToggle如何不再传入,           isOpen = {this.state.openAll} // ONLY openAll作为prop`isOpen传入           text = {this.props.text +''+ i}         /&GT;       );     }     回来(       &LT; DIV&GT;         &lt; Button text =“Expand All”onExpandAll = {()=&gt; this.onExpandAll(true)} /&gt;         &lt; Button text =“Collapse All”onExpandAll = {()=&gt; this.onExpandAll(false)} /&gt;         {}标题       &LT; / DIV&GT;     );   }   onToggle(){     this.setState({//这可以取消注释,       openAll:true //它不会在TitleToggleContainer中使用     });   }   onExpandAll(isAllOpen){     this.setState({       openAll:isAllOpen     });   } } 新的TitleToggleContainer类: class TitleToggleContainer扩展了React.Component {   构造(道具){     超级(道具);     this.state = {isOpen:true};     this.localToggle = :: this.localToggle; //绑定方法的另一种方法   }   localToggle(){     this.setState({isOpen:!this.state.isOpen});   }   componentWillReceiveProps(nextProps){//你还需要这个才能收到     this.setState({// prop从父Toggle更改       isOpen:nextProps.openAll?真假     });   }   渲染(){     const titleComponent = this.state.isOpen? &lt; h3 style = {{display:“inline-block”}}&gt; {this.props.text}&lt; / h3&gt; : 空值;     回来(       &LT; DIV&GT;         &lt;切换onClick = {this.localToggle} /&gt;         {} titleComponent       &LT; / DIV&GT;     );   } }