2016-11-05 69 views
0

我一直在寻找几天,似乎无法得到这个工作,它让我疯了!从父母“一击”修改孩子状态

目标是增加“全部展开”/“全部折叠”按钮的手风琴。通过将propAll属性传递给子组件,并通过更新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/

+0

您的页眉组件不应该有'状态'。改用道具。 –

回答

0

你需要从在App组件传递一个道具给它的“collapseAll”状态的头。我更新了头的呈现在应用程序像这样:

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

然后头组件需要侦听conponentWillReceiveProps该道具的变化,并相应地设置自己的状态,像这样:

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

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

+0

这正是我之前所做的,我原本是这样做的,但在设置状态之前没有做检查,因此我看到了这种行为。 Cheers Ben –

+0

Awesome Aamir :-) –

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:想把它扔在你的空间&缩进让它更难以阅读你的代码= |