在加载Firestore数据之前进行React App渲染

时间:2019-02-09 01:39:31

标签: reactjs firebase components render

我正在尝试从Firestore加载数据并将其显示在甘特图中,但是它是在从Firebase加载数据之前进行渲染的。因此,我在componentDidMount内部调用setState,因为我认为这将再次调用渲染器,此时数据将在那里。但是它仍然空着。有什么想法吗?

import React, { Component } from 'react';
import Gantt from './Gantt';
import Toolbar from './Toolbar';
import MessageArea from './MessageArea';
import Firebase from './Firebase';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentZoom: 'Days',
      messages: [],
      projects: [],
      links: []
    };

    this.handleZoomChange = this.handleZoomChange.bind(this);
    this.logTaskUpdate = this.logTaskUpdate.bind(this);
    this.logLinkUpdate = this.logLinkUpdate.bind(this);
  }

  componentDidMount() {
    const db = Firebase.firestore();
    var projectsArr = [];
    db.collection('projects').get().then((snapshot) => {
        snapshot.docs.forEach(doc => {
            let project = doc.data();
            projectsArr.push({id: 1, text: project.name, start_date: '15-04-2017', duration: 3, progress: 0.6});
        });
    });

    this.setState({
      projects: projectsArr
    });
  }

  addMessage(message) {
    var messages = this.state.messages.slice();
    var prevKey = messages.length ? messages[0].key: 0;

    messages.unshift({key: prevKey + 1, message});
    if(messages.length > 40){
      messages.pop();
    }
    this.setState({messages});
  }

  logTaskUpdate(id, mode, task) {
    let text = task && task.text ? ` (${task.text})`: '';
    let message = `Task ${mode}: ${id} ${text}`;
    this.addMessage(message);
  }

  logLinkUpdate(id, mode, link) {
    let message = `Link ${mode}: ${id}`;
    if (link) {
      message += ` ( source: ${link.source}, target: ${link.target} )`;
    }
    this.addMessage(message)
  }

  handleZoomChange(zoom) {
    this.setState({
      currentZoom: zoom
    });
  }  

  render() {

    var projectData = {data: this.state.projects, links: this.state.links};

    return (
      <div>
        <Toolbar
            zoom={this.state.currentZoom}
            onZoomChange={this.handleZoomChange}
        />
        <div className="gantt-container">
          <Gantt
            tasks={projectData}
            zoom={this.state.currentZoom}
            onTaskUpdated={this.logTaskUpdate}
            onLinkUpdated={this.logLinkUpdate}
          />
        </div>
        <MessageArea
            messages={this.state.messages}
        />
      </div>
    );
  }
}
export default App;

1 个答案:

答案 0 :(得分:1)

您正在setState回调之外调用then

所以改变

   db.collection('projects').get().then((snapshot) => {
         snapshot.docs.forEach(doc => {
             let project = doc.data();
             projectsArr.push({id: 1, text: project.name, start_date: '15-04-2017', duration: 3, progress: 0.6});
         });
     });

     this.setState({
       projects: projectsArr
     });

收件人

   db.collection('projects').get().then((snapshot) => {
        snapshot.docs.forEach(doc => {
             let project = doc.data();
             projectsArr.push({id: 1, text: project.name, start_date: '15-04-2017', duration: 3, progress: 0.6});
         });
        this.setState({
             projects: projectsArr
        });
});

此外,作为一般模式,您可以执行以下操作:

    class AsyncLoad extends React.Component {
      state = { data: null }

      componentDidMount () {
        setTimeout(() => {
          this.setState({ data: [1, 2, 3]})
        }, 3000)
      }

      render () {
        const { data } = this.state
        if (!data) { return <div>Loading...</div> }
        return (
          <pre>{JSON.stringify(data, null, 4)}</pre>
        )
      }
    }

这是为它创建HOC的足够常见的操作。