2017-08-04 70 views
2

我的应用有时会接收大量需要解析和渲染的数据。我想解析第一对消息,并渲染它们给用户一些工作,而其余的消息在后台解析。问题是,下图中的第一次渲染不会导致屏幕画出Chrome,Firefox或Safari。React 2级渲染Promise在第一次承诺解决后不渲染

enter image description here

parse(data, show) { 
    if (data === null) { 
     ... 
    } 
    else { 
     if (data.length > 100) { 
      let taste = []; 
      taste.push(data.pop()); 
      taste.push(data.pop()); 

      console.log('start'); 
      const messagePromise = this.props.parser.parseMessages(taste); 
      console.log('promise 1 created'); 

      const restPromise = messagePromise.then(result => { 
      console.log('first chunk resolved, setting state!'); 
      if (this.state.messageDetail === null) 
       this.setState({messageDetail: result[0]}); 
      this.setState({parsedMessages: this.state.parsedMessages.concat(result)}); 
      return this.props.parser.parseMessages(data); 
      }); 
      console.log('promise 2 created'); 

      restPromise.then(result => { 
       console.log('second chunk resolved, setting state!'); 
       if (this.state.messageDetail === null) 
       this.setState({messageDetail: result[0]}); 
       this.setState({parsedMessages: this.state.parsedMessages.concat(result)}); 
     }); 
     console.log('leaving parse'); 
    } 

这种方法parse为道具,以一个子组件时,他有一些消息来分析谁调用它传递。还有另外两个子组件显示消息列表和选定消息的详细信息。这些组件具有parsedMessagesmessageDetail作为道具传递,因此当父母的状态发生变化时,孩子们会重新投入自己。

任何人都看到渲染不会导致这样的画面绘制的问题?我以为我挡住了某处,但在19:16:34.630的日志中看到render让我觉得有其他事情正在发生。

我使用的是最新的React(15.6.1)和最新的浏览器。

enter image description here

所以看起来像页面不画,直到的onClick回报。我认为这会在promise 2创建之后但resolve发生之前马上发生。也许我误解了承诺如何工作。当this.props.parser(...)返回时,onClick()势必handleSubmit()this.props.parser()绑定到parse()上述方法,我们可以从控制台日志退出在19:16:34:619

+0

'setState'async? – marekful

+0

docs说:setState()不会立即改变this.state,但会创建一个挂起的状态转换。调用此方法后访问this.state可能会返回现有值。无法保证对setState的调用进行同步操作,并且可能会调用批处理以提高性能。 – shaz

+0

这是关于调用批处理的那一点让我很担心,但是'render'指示'setState()'成功完成并且实际上触发了具有从属状态的子项中的渲染。 – shaz

回答

0

bloodyowl在https://github.com/facebook/react/issues/7678看到

 <RaisedButton onClick={this.handleSubmit.bind(this)} label="Parse" style={leftButtonStyle} secondary={true} disabled={!this.state.parseEnabled}/> 

handleSubmit() { 
    let messages = this.state.value.split('\n'); 
    this.props.parser(messages, true); 
} 

handleSubmit()应该做解决问题。仍然不确定为什么承诺是不够的(可能是因为它正在被转译?),但是执行初始部分render()然后在componentDidUpdate() - 如果在setState()回调中执行,则不起作用 - 将第2阶段处理包装在setTimeout(doParsing, 0)打破了连锁可以说,并允许初始渲染画。