React load data into state

I am converting my app to react and there are a few things I don’t get. I have a form where I add rows (so I want to extend an array). I do not care about knowing if this record is updated in the database I just want to populate my form and state. How do I do this?

“normally” I would just use the ReactMeteorData mixin and use the getMeteorData method to subscribe and then populate this.data. But I dont need this.data, I want to set component state variables (which isn’t allowed in getMeteorData()).

Example of what I want to do but is not allowed to:

 getMeteorData() {
    var data = {};
    var id = this.props.id;
    var handle = Meteor.subscribe('emailGroups');

    if (handle.ready()) {
        var emailGroup  = EmailGroups.findOne(id);

       // Not allowed to set state here.

        this.setState({
            name : emailGroup.name,
            description : emailGroup.description,
            emails : emailGroup.emails,
        });
    }

    return data;
}

In a blaze template I would use a Tracker to solve this.

1 Like

Why dont you use Tracker now? Or handle subscribe callback?

componentDidMount() {
  this.sub = Meteor.subscribe("itemsRefs", (err) => {
    let item = Items.findOne(this.props.id) || {};
    let state = _.pick(item, "name", "descr");
    this.setState(state);
  });
}
2 Likes

I don’t fully understand what you’re trying to do but do you remember what reactive vars are? :slight_smile: those still exist

I was being an idiot. I thought tracker only worked in blaze template
method for some reason. Having a hard time finding good meteor react
documentation/examples. Thanks for your help, I will try that.

1 Like

Inside getMeteorData you should not set a state. You should return your cursors to access them via this.data.variable. In your render method, you can set states.

Or use Tracker-React

In case I miss understood what you try to achieve (regarding reactivity), read this:

Using that approach will component re-render if database changes? I dont
want that, just asking.

Yeah, calling setState inside getMeteorData could trigger a loop or overflow the call stack for autoruns dealing with getMeteorData. And yes it rtiggers component re-render everytime when any of reactive source inside getMeteorData are changed.

1 Like

Does it matter if I use componentDidMount or componentWillMount . I mean componentWillMount() fires before so then the reference to this.sub is available in the render method(so I can check if the subscription is ready and render accordingly).

Yes you could. But note that sub.ready() != all data is available on the client.
According to Meteor docs subscribtion.ready() is reactive data source so you should handle callback or wrap all the checks inside Tracker.autorun and it is no matter where you define sub variable if you put ready result into the state. See the sample:

componentWillMount: ->
  # this.sub is defined before render (awailable inside componentDidMount and render)
  this.sub = Meteor.subscribe('subName')
  Tracker.autorun () =>
    if this.sub.ready() then this.setState({ready: true})
render: ->
  isReady = this.state.ready 

or with ReactMeteorData mixin

componentWillMount: ->
  this.sub = Meteor.subscribe('subName')
getMeteorData: ->
  return {ready: this.sub.ready()}
render: ->
  isReady = this.data.ready

When dealing with getMeteorData just note that it will trigger re-render if sub ready. It works like FAT Tracker.autorun

1 Like