2017-08-04 84 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)打破了連鎖可以說,並允許初始渲染畫。