子组件状态未更新

时间:2017-04-09 14:03:20

标签: reactjs

这是我进入React的第一周。我发现涓滴状态的实现是难以捉摸的。

我想要发生的事情:当父容器从套接字收到消息时,我希望父级的状态更改向下逐渐渗透到每个子元素。

当前正在发生的事情:使用下面的代码将所有组件呈现到屏幕上,接收消息,但子元素不会注册任何类型的更新。

**更新:如果我不将ProgressBlock循环到数组中,然后将该数组放在带有{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} />
  }
}

1 个答案:

答案 0 :(得分:0)

子元素中的constructor被调用一次,因此您的状态不会在子元素中更新。它也是一个反模式,它在构造函数中依赖于props时设置状态。您应该在更新道具时调用的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} />
  }
}