2017-04-09 82 views
0

这是我进入React的第一周。我发现滴落状态的实现是难以捉摸的。子组件状态未更新

我想发生:当父容器从插座上收到一条消息,我希望父的状态变化逐步应用到每个子元素。

什么是当前发生的:随着下面的代码渲染到屏幕上的代码,收到的消息,但子元素没有注册任何类型的更新。

**更新:如果我不将ProgressBlock s循环到一个数组中,然后将该数组放入渲染树中,并且使用{this.state.blocks},则一切正常。这是不幸的,因为它不具有活力,但至少有进展。

父容器

class InstanceContainer extends React.Component { 

    constructor(props) { 
    super(props) 

    this.state = { 
     id: ids.pop(), 
     callInProgress: false, 
     callsCompleted: 0, 
     eventProgress: 0, 
     blocks: [] 
    } 
    } 

    componentWillMount() { 

    const lightColors = ['white', 'white', 'cyan', 'green', 'green', 'yellow', 'orange', 'magenta', 'red'] 
    for (let i = 0; i < 10; i++) { 
     this.state.blocks.push(<ProgressBlock bgColor={lightColors[i]} eventPlace={i} eventProgress={this.state.eventProgress} />) 
    } 
    } 

    render() { 

    socket.on(this.state.id, (msg) => { 
     console.log(msg) 
     console.log('RECEIVED MESSAGE') 
     console.log(this.state.id) 

     if (msg) { 
     this.setState((prevState) => ({ 
      eventProgress: 0, 
      callsCompleted: prevState.callsCompleted + 1 
     })) 
     } else { 
     this.setState((prevState) => ({ 
      eventProgress: prevState.eventProgress + 1 
     })) 
     } 

     console.log(this.state.eventProgress) 

    }) 

    return (
     <div className="instance-container" id={this.state.id}> 
     {this.state.blocks} 
     <CompletionCounter callsCompleted={this.state.callsCompleted} /> 
     <DisplayLog /> 
     <VenueName /> 
     </div> 
    ) 
    } 
} 

子元素

class ProgressBlock extends React.Component { 

    constructor(props) { 
    super(props) 

    this.state = { 
     light: false, 
     eventProgress: this.props.eventProgress, 
     bgColor: this.props.bgColor 
    } 
    } 

    componentWillUpdate() { 
    if (this.state.eventProgress >= this.props.eventPlace) { 
     this.setState({ 
     light: true 
     }) 
    } 
    } 


    render() { 

    console.log(this.state.eventProgress) // Does not log when parent changed 
    console.log(this.props.eventPlace) // Does not log when parent changed 

    const styleObj = { 
     backgroundColor: '#232323' 
    } 

    if (this.light) { 
     const styleObj = { 
     backgroundColor: this.props.bgColor 
     } 
    } 

    return <div className="progress-block" style={styleObj} /> 
    } 
} 

回答

0

的子元素的constructor被调用一次,因此你的状态没有gettinng的子元素更新。它也是一个反模式,用来在构造函数中设置状态,这取决于道具。您应该在更新道具时调用componentWillReceiveProps生命周期函数中执行此操作。看到下面的代码

class ProgressBlock extends React.Component { 

    constructor(props) { 
    super(props) 

    this.state = { 
     light: false, 
     eventProgress: '', 
     bgColor: '' 
    } 
    } 
    componentWillMount() { 

     this.setState({eventProgress: this.props.eventProgress, bgColor: this.props.bgColor}); 
} 
    componentWillReceiveProps(nextProps) { 
    this.setState({eventProgress: nextProps.eventProgress, bgColor: nextProps.bgColor}); 
    } 
    componentWillUpdate() { 
    if (this.state.eventProgress >= this.props.eventPlace) { 
     this.setState({ 
     light: true 
     }) 
    } 
    } 


    render() { 

    console.log(this.state.eventProgress) 
    console.log(this.props.eventPlace) 

    const styleObj = { 
     backgroundColor: '#232323' 
    } 

    if (this.light) { 
     const styleObj = { 
     backgroundColor: this.props.bgColor 
     } 
    } 

    return <div className="progress-block" style={styleObj} /> 
    } 
} 
+0

我没有看到'componentWillReceiveProps'在任何点执行。无论是初始化还是父状态更改。只有在初始化时调用'componentWillUpdate'。 –

+0

'componentWillReceiveProps'不是最初执行的,但每次道具改变后。尝试更新的答案 –