繁体   English   中英

无限循环中的反应代码锁定 - 不涉及循环

[英]React code locking in endless loop - no while loops involved

对React有点新,并在下面编写了这段代码。 下面的组件用于渲染故事的时间和日期选择器。 时间和日期选择器仅为那些计划出现故事的社交媒体呈现。

class TaleScheduler extends Component {
  constructor(props) {
    super(props);
    this.state = {
      returnData: {},
      totalNeeded: numberOfChannels(this.props.data)
    };
  }
  setSchedule = (date, channel) => {
    const returnData = update(this.state.returnData, {
      $merge: {channel: date}
    })
    this.setState({returnData: returnData})
    const { data, ScheduleTale } = this.props
    if (Object.values(this.state.returnData).length === this.state.totalNeeded) {
      FireAction(this.state.returnData, data.id)
    }
  }
  render() {
    const { data } = this.props
    return (
      <div style={{"display": "inline-block"}}>
        {data.showOnFacebook ? (<DateTimePicker data={data} image={facebook} setSchedule={this.setSchedule} />) : null}
        {data.showOnTwitter? (<DateTimePicker data={data} image={instagram} setSchedule={this.setSchedule} />) : null}
        {data.showOnInstagram ? (<DateTimePicker data={data} image={twitter} setSchedule={this.setSchedule} />) : null}
        {data.showOnApp ? (<DateTimePicker data={data} image={app} setSchedule={this.setSchedule} />) : null}
        <FlatButton label="Schedule" onClick={this.setSchedule} />
      </div>
    )
  }
}

这将根据故事的显示位置呈现一组时间和日期选择器。 下面是正在显示的组件

class DateTimePicker extends Component {
  constructor(props) {
    super(props);
    this.state = {
      date: null,
      time: null
    };
  }
  handleDateInput = (event, date) => {
    this.setState({
      date: date
    })
  }
  handleTimeInput = (event, time) => {
    this.setState({
      time: time
    })
  }
  componentDidUpdate(prevProps, prevState) {
    const {setSchedule, channel} = this.props
    if (this.state.date && this.state.time) {
      setSchedule(concatenateDateAndTime(this.state.date, this.state.time), channel)
    }
  }
  render() {
    return (
      <List>
        <ListItem
        leftAvatar={
          <img src={this.props.image} style={styles.scheduledChannelImgStyle} />
        }>
        </ListItem>
        <ListItem>
          <DatePicker onChange={this.handleDateInput} />
        </ListItem>
        <ListItem>
          <TimePicker onChange={this.handleTimeInput} />
        </ListItem>
      </List>
    )
  }
}

选择上面的日期和时间。 整个页面锁定一个无限循环,导致页面冻结。 我确信这些函数正在循环中相互调用。 但我不太了解React渲染能够弄清楚原因。

原因是您在componentDidUpdate生命周期方法中调用方法setSchedule setSchedule方法正在调用setState() 这导致对componentDidUpdate的调用,该调用随后再次调用setState 你正在创建一个无限循环,因为没有中断条件。 您可以在componentWillReceiveProps调用setState而不是componentDidUpdate

  componentDidUpdate(prevProps, prevState) {
    const {setSchedule, channel} = this.props
    if (this.state.date && this.state.time) {
      setSchedule(concatenateDateAndTime(this.state.date, this.state.time), channel)//Calling method that calls setstate.
    }
  }

componentDidUpdate ,在调用函数之前检查previous date and time state values ,否则只要定义了日期和时间并且组件正在更新它将在每次调用setSchedule函数时执行更新状态和父级时将调用它这会导致更新的道具传递给子组件。

尝试

componentDidUpdate(prevProps, prevState) {
    const {setSchedule, channel} = this.props
    if(prevState.date !== this.state.data || prevState.time !== this.state.time) {
        if (this.state.date && this.state.time) {
           setSchedule(concatenateDateAndTime(this.state.date, this.state.time), channel)
        }
    }
  }

要确认父组件中的任何更新,调用子组件componentDidUpdate ,请查看此代码段

 class Parent extends React.Component { constructor(props) { super(props); this.state = { clicked: false } } render() { return ( <div> <Child /> <button onClick={() => this.setState((prevState) => ({clicked: !prevState.clicked}))} > Toggle</button> </div> ) } } class Child extends React.Component { componentDidUpdate(prevProps, prevState) { console.log('update in child called'); } render() { return ( <div> Hello Child </div> ) } } ReactDOM.render(<Parent/>, document.getElementById('app')); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM