question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Subscriptions ready fires before Data has arrived (React)

See original GitHub issue

So i am having an issue with a subscription being ready before the data has fully been served to the client. I am using ReactJS as a templating engine and I am passing the a user property to child templates. When i come to a setting page I need to subscribe to a specific piece of the users account and display that information in input fields to be edited.

However,

if the data has not quite hit the client the subscription is being set to ready before the template has the data to render. I’m not sure if its react slowing things down or what but here are a few example snippets that have been striped down.

LayoutTemplate

PortalLayout = React.createClass({
  mixins : [ReactMeteorData],
  getMeteorData () {
    return {
      user : Meteor.user()
    }
  },
componentDidMount() {
    let instance = this;
    instance.tracker = Tracker.autorun(function () {
      FlowRouter.watchPathChange();
      if (instance.isMounted()) {
        let holder = instance.state;
        holder.current = FlowRouter.current();
        instance.setState(holder);
      }
    });
  },
 componentWillUnmount () {
   this.tracker.stop()
  },
  render() {

    if(!this.data.user) {
      return <div></div>
    }

    return (

        <div className="main-container">
          { React.cloneElement(this.props.content, { user: this.data.user }) }
        </div>

    )
  }

Child Template


InsuranceSettings = React.createClass({
  componentDidMount () {
    let instance = this;

    instance._tracker = Tracker.autorun(function  () {
      let user = Meteor.user();
      let holder = instance.state;

      if(user && user.documents) {
        holder.exempt = user.documents.exempt;
      }

      holder.ready = FlowRouter.subsReady();
      instance.setState(holder);

    });

  },
  componentWillUnmount() {
    this._tracker.stop();
  },
  getInitialState () {
    return {
      exempt : 'no',
      ready : FlowRouter.subsReady()
    }
  },
  setExempt (event) {
    let holder = this.state;
    holder.exempt = $(event.target).val();
    this.setState(holder);
  },
  render () {
    let instance = this;

    if(!instance.state.ready || (instance.props.user && instance.props.user.documents && !instance.props.user.documents.glExp ))
      return (<div></div>);

    return (
      <div className="settings page block" id="account-settings">
        <form className="centered" ref="form">
          <h2>Insurance</h2>
          <label>General Liability</label>
          < FileUpload uploader="documents" name="gl" file={instance.props.user.documents && instance.props.user.documents.gl || null } />
          <label>General Liability Expiration</label>
          <input type="text" name="glExp" data-date defaultValue={instance.props.user.documents && instance.props.user.documents.glExp && instance.props.user.glExpDate() || '' } />

          <button type="button" className="pull-right" >Update Account</button>
        </form>
      </div>
    )
  }
});

Since React’s defaultValue only sets the value on load i have to check if the values exist and if they don’t if(!instance.state.ready || (instance.props.user && instance.props.user.documents && !instance.props.user.documents.glExp )) then I have to render nothing until they do. But this doesnt always work because if glExp is sent before gl then glExp will have a value but gl won’t.

If anyone has any ideas solutions or if this is the wrong place to ask this please let me know.

Thank you.

Issue Analytics

  • State:open
  • Created 8 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
arunodacommented, Nov 12, 2015

Okay. Here’s the issue. getMeteorData() does more stuff and when manually setting state. There could be some conflict. So, I advice you to put flow router code on the getMeteorData itself. Then it’ll work without any issues.

PortalLayout = React.createClass({
  mixins : [ReactMeteorData],
  getMeteorData () {
    const ready = FlowRouter.subsReady();
    if(!ready) {
      return {};
    }

    return {
      user : Meteor.user()
    }
  },
  render() {

    if(!this.data.user) {
      return <div></div>
    }

    return (

        <div className="main-container">
          { React.cloneElement(this.props.content, { user: this.data.user }) }
        </div>

    )
  }
}
0reactions
andrewlorenzcommented, Feb 18, 2017

I’m now using react-router plus react-meteor-data instead of flow-router - works perfectly.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React: How to wait data before using "this.state.x" into a ...
You're going to need to conditionally render. Provide a loading state to be loaded prior to asynchronously required data.
Read more >
Rendering and Updating Data using Component Lifecycle ...
A React component can be created using a function or a class-based component, and the class-based component can use different lifecycle hooks.
Read more >
Update on Async Rendering – React Blog
The new static getDerivedStateFromProps lifecycle is invoked after a component is instantiated as well as before it is re-rendered.
Read more >
react-meteor-data v2.2.1 - unnecessary renders · Issue #313
Once it becomes true, I load my app for real. ie, I don't want to load my app until the subscription is ready...
Read more >
How to fetch data in React with performance in mind
Deep dive into data fetching in React. What is performance, fundamental libraries-agnostic patterns and techniques, how react lifecycle and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found