修改父状态的子状态“一次点击”

Modify a child state from parent "one hit"

本文关键字:状态 一次 一次点击 修改      更新时间:2023-09-26

我已经搜索了好几天了,似乎不能让这个工作,它把我逼疯了!

目标是一个手风琴,增加了一个"展开全部"/"折叠全部"按钮。我设法通过props将expandAll属性传递给子组件,并在componentWillReceiveProps中更新子组件的展开状态,从而在某一点上实现了这一点,但如果父组件被设置为在计时器上自动获取数据,那么这意味着在第二次获取后,子状态被更新为折叠或展开所有面板,这不是必需的行为。

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      "teams": [{ Name: "Liverpool", Players: ["Lovren", "Coutinho"]}, {Name:"Arsenal", Players: ["Ozil", "Welbeck"]},{Name: "Chelsea", Players: []}],
      toggleAll: false,
      toggleText: "Expand All"
    }
  }
  _toggleAll(event){
    event.preventDefault();
    let text = "Expand All";
    if (!this.state.toggleAll === true){
      text = "Collapse All"
    }
    this.setState({toggleAll: !this.state.toggleAll, toggleText: text});
    console.log("toggleAll", this.state.toggleAll);
  }

  render() {
    return (
      <div className="headers">
        <button onClick={this._toggleAll.bind(this)}>{this.state.toggleText}</button>
        {this.state.teams.map((team, index) =>
                                        <Header className="" key={index} title={team.Name} players={team.Players}  />
        )}
      </div>
    );
  }
}
class Header extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      expanded: false
    }
  }
  componentWillMount(){
    console.log(this.props.title);
    console.log(this.props.players);
  }
  _expand(event){
    event.preventDefault();
    this.setState({expanded: !this.state.expanded});
  }
  render() {
    let players;
    if(this.state.expanded)
    {
      players= <ul>
                  {this.props.players.map((player, index) => <li key={index}>{player}</li>)}
               </ul>
    }
    return (
      <div>
        <div className="header"  >
          <p onClick={this._expand.bind(this)}>{this.props.title}</p>
        </div>
        {players}
      </div>
    );
  }
}

React.ReactDOM.render(
  <App />,
  document.getElementById('container')
);

小提琴提供如下https://jsfiddle.net/aamirjaffer/x52bhdq6/

你需要从App组件传递一个prop来给header设置为"collapseAll"状态。我在App中更新了标题的渲染,如下所示:

<Header 
  className = ""
  key={index}
  title={team.Name}
  players = {team.Players}
  allExpanded={this.state.toggleAll}
/>

然后Header组件需要侦听componentwillreceiveprops上的prop变化,并相应地设置自己的状态,如下所示:

componentWillReceiveProps(nextProps) {
    if (nextProps.allExpanded !== this.props.allExpanded) {
    this.setState({ expanded: nextProps.allExpanded });
  }
}

我分叉了你的小提琴,这些变化,它都工作得很好:https://jsfiddle.net/xkp4snmx/

您可以存储每个团队的崩溃状态。

this.state = {
  teams: [
  {
    Name: "Liverpool",
    Players: ["Lovren", "Coutinho"],
    collapsed: true
  },
  {
    Name: "Arsenal",
    Players: ["Ozil", "Welbeck"],
    collapsed: true
  },
  {
    Name: "Chelsea",
    Players: ["Hazard", "Oscar", "Willian"],
    collapsed: true
  }
  ]
}

js fidds

ps:我可能会渲染播放器列表不管,只是隐藏它通过css -少计算和css你可以给它一个真正的手风琴感觉整洁的动画。

pss:想把它放在你的空格&缩进让你的代码更难读=|