Search code examples
reactjsmeteorconstructormeteor-tracker

how to set initial state values in react component constructor only after meteor subscription is complete


I am using React and Meteor for my application. I need to initialize state values using records from collections, However meteor subscription takes time to return collection records. Due to this delay in getting subscribed records my state value in components constructor are being loaded with undefined values. How can i call the reacts constructor only once subscription is ready. Note: I do not want to setState value in render method after the subscription is ready, I want to do it in constructor itself so that I can compare my original state values with later updates in collections.

class DataTable extends Component {
  constructor(props) {
    super(props);
    this.state = {
      records: this.props.records
    };
    //since initially records were empty state value is initialised as undefined
    console.log(this.state.records);
  }

  render() {
return something
}
}
export default withTracker(() => {
  //withTracker seems to be giving some issue when rendering the component for first time
  //and giving empty values 
  Meteor.subscribe("records");
  return {
    records: Records.find({}).fetch()
  };
})(DataTable);

Solution

  • You can do it by introducing an intermediate <Loader> component, that gets rendered when the data is not ready. It only renders your component when it has data. The code will look like this:

    const Loader = props => {
      if (props.loading) return <div>Loading...</div>
      // This only gets rendered when we have data
      return <DataTable {...props} />
    }
    
    export default withTracker(() => {
      //withTracker runs twice - that is normal
      const subsHandle = Meteor.subscribe("records");
      const loading = !subsHandle.ready()
      return {
        loading, 
        records: Records.find({}).fetch()
      };
    })(Loader); // Render the Loader component
    

    What this also means is that your DataTable component can have PropTypes that are required, eg for props.records