getMeteorData and getInitialState load order?

Quick one, I’m getting currentUser is undefined from this code:

  // Bio component
  Bio = React.createClass({
  mixins: [ReactMeteorData],

getMeteorData() {
  return {
    currentBio: Meteor.user()
  }
},

getInitialState: function() {
  return ({value: this.data.currentUser.profile.bio });
},

handleChange: function(event) {
  this.setState({value: event.target.value});
},

bioSubmit(event) {
  event.preventDefault();

  // Parse the input
  var bioInput = document.getElementById( "bio-field" ).value;
  var bioParse = parseMarkdown( bioInput );

  Meteor.users.update({
    _id: Meteor.userId()
  }, {
    $set: {
      'profile.bio': bioParse
    }
  });
},

render: function() {
  var value = this.state.value;
  return (
    <form onSubmit={this.bioSubmit}>
      <div className="form-group">
        <h3>Bio</h3>
        <textarea className="form-control sharp" id="bio-field" value={value} onChange={this.handleChange}></textarea>
      </div>
      <button type="submit" className="btn btn-primary sharp">Submit</button>
    </form>
  )
}
});

(I’m not messing around with the code snippet above, Discourse seems to be buggy with code input atm)

I’m assuming it’s because React is using getInitialState before getMeteorData so the currentUser will be undefined? If so, then does anyone have a workaround? And if not, does anyone know why I’m getting undefined!? This profile stuff is getting a bit annoying now, the rest of my app is pretty much done and I’ve run into loads of roadblocks on the last bit (typical really…)

Cheers.

Instead of tying your textarea’s value to the state, tie it directly to your Meteor data. That’s what it’s there for:

<textarea className="form-control sharp" id="bio-field" value={this.data.currentBio} onChange={this.handleChange}>
1 Like

EDIT: Wrong version of my code!

Hi sergio,

Not quite there yet! It’s now not showing as undefined, but it’s now not letting me type in the textarea.

Here is the textarea code now:

<textarea className="form-control sharp" id="bio-field" value={ this.data.currentUser.profile.bio } onChange={this.handleChange}></textarea>

And I updated getMeteorData to simply get the user as normal:

getMeteorData() {
  return {
    currentUser: Meteor.user()
  }
},

Any further ideas? Thanks for your help!

Oh yeah, change value to defaultValue. :rocket:

I’d do this:

getBioContents() {
  return this.state.bio || this.data.bio;
}

then, in handleChange, update this.state.bio.

Then, when the user hits submit, call a Meteor Method with the new value, and when it completes clear the component state.

Basically, the rule of thumb is - never copy data into state.

2 Likes

You, Sir, are a gentleman and a scholar! Sorted now. Not seen defaultValue yet, not even in the react docs I’ve looked through!

Thanks a lot :smile:

Awesome, glad it worked.

So basically:

defaultValue: What’s going into the value on initial React component load.

value: What’s going into the value after every render()

I think, lol.

1 Like