从父“一击”修改子状态

时间:2016-11-05 14:53:50

标签: javascript reactjs

我一直在寻找几天,似乎无法让它发挥作用,这让我疯了!

目标是增加一个“全部展开”/“全部折叠”按钮的手风琴。我设法通过将一个expandAll属性通过props传递给子组件并在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/

2 个答案:

答案 0 :(得分:0)

你需要从App组件中传递一个道具,以便为它提供标题&#34; collapseAll&#34;州。我在App中更新了标题的呈现,如下所示:

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

然后,Header组件需要在conponentWillReceiveProps上侦听该prop更改并相应地设置它自己的状态:

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

我分叉了你的小提琴,这些改变,一切正常:https://jsfiddle.net/xkp4snmx/

答案 1 :(得分:0)

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

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:想把它扔进你的间距&amp;缩进使你更难以阅读你的代码= |