React in Meteor app. Set state with getMeteorData or getInitialState? Use both?

Having a really productive day here, sorry for posting so many questions but I’m in the flow.

Here’s a simple component I’m writing that allows users to update their profile information.

Settings = React.createClass({
  mixins: [ReactMeteorData],
  getMeteorData() {
      return {
          currentUser: Meteor.user()
      };
  },

  openUploadCareDialog: function() {
    var self = this;
    uploadcare.openDialog().done(function(file) {
      file.promise().done(function(fileInfo){
        var avatarImage = ReactDOM.findDOMNode(self.refs.avatarImagePreview);
        $(avatarImage).attr('src', fileInfo.cdnUrl);

        var avatar = ReactDOM.findDOMNode(self.refs.avatarImage);
        $(avatar).val(fileInfo.cdnUrl);
      });
    });
  },

  validate: function(e) {
    Meteor.call('validateUsername', e.target.value, function(err, data) {
      if (!data.valid) {
        // Username is invalid, show error message.
        console.log(data.reason);
      }
    });
  },

  updateProfile: function(e) {
    e.preventDefault();

    if (validate()) {
      console.log("Saving changes...");
    }
  },

  render: function() {
    return (
      <div className="container">
        <!-- HTML snipped -->
      </div>
    );
  }
});


So I’ve been thinking about how React works and the tl:dr is you modify the state (underlying data structure) and the UI will reflect that.

However if you look at my openUploadCareDialog() function, I’m modifying the elements using jQuery. Doesn’t really feel right.

How can I improve this approach and use React’s underlying state mechanism within Meteor. Is it recommended to use both getMeteorData and getInitialState (for data that’s not tied to a meteor object) ?

1 Like

maybe something like this… haven’t tested it obviously, and i am a few glasses of wine into my friday night :stuck_out_tongue_winking_eye:

Settings = React.createClass({
  mixins: [ReactMeteorData],
  getMeteorData() {
      return {
          currentUser: Meteor.user()
      };
  },
  getInitialState(){
    return {
      avatarImagePreview: null,
      avatarImage: null
    };
  },
  openUploadCareDialog(){
    uploadcare.openDialog().done((file) => {
      file.promise().done((fileInfo)=>{
        this.setState({
          avatarImagePreview: this.refs.avatarImagePreview,
          avatarImage: this.refs.avatarImage
        });
      });
    });
  },
  validate(e){
    Meteor.call('validateUsername', e.target.value, function(err, data) {
      if (!data.valid) {
        // Username is invalid, show error message.
        console.log(data.reason);
      }
    });
  },
  updateProfile(e){
    e.preventDefault();

    if (validate()) {
      console.log("Saving changes...");
    }
  },
  render() {
    return (
      <div className="container">
        <img src={this.state.avatarImagePreview} />
        <img src={this.state.avatarImage} />
      </div>
    );
  }
});

edit: just to add a couple of explanatory remarks:

  • you can definitely use both
  • with ES6 you don’t need to do self = this as long as you use arrow functions
  • with some recent version of react, you don’t need all that findDOMnode stuff… just this.refs.whatever is enough
1 Like

Awesome, it’s nice to know that getInitialState works as well. I’m adding some state goodness now, thank you!

1 Like

no prob, btw, there are a bunch of React users Meteor’s gitter channel, stop on by

Do you have a link by any chance?

1 Like