paypal / react-engine

a composite render engine for universal (isomorphic) express apps to render both plain react views and react-router views
Apache License 2.0
1.45k stars 130 forks source link

props for a react component losing it's prototype data on client side #142

Closed cryptic-mystic closed 8 years ago

cryptic-mystic commented 8 years ago

Hey there! To preface, I'm new to server side js, and to isomorphic js, and to object oriented JS in general. So I'm not sure if what I'm doing is the 'right' way to do things, but it feels OO to me.

So I'm trying to render a simple anchor tag that points to GitHub's OAuth url. In an attempt to be OO I created this class to represent it:

function GitHubLoginRequest(clientId) {
  this.params = {
    "client_id": clientId,
    "redirect_uri": "http://127.0.0.1:3000/",
    "scopes": "user,repo,notifications",
    "state": "ks0i32nknd0ij0239443ms"
  }
  this.requestUrl = "https://github.com/login/oauth/authorize"
}

GitHubLoginRequest.prototype.getAuthUrl = function() {
  var requestParams = this.params;
  return this.requestUrl + "?" + Object.keys(requestParams).map(function(key) {
    return key + '=' + encodeURIComponent(requestParams[key]);
  }).join('&');
};

module.exports = GitHubLoginRequest;

This object is initialized server-side with a client id, and then passed to my react component:

var Login = React.createClass({
  propTypes: {
    LoginRequest: React.PropTypes.instanceOf(GitHubLoginRequest).isRequired
  },
  getInitialState: function() {
    return {
      isAuthenticating: false
    };
  },
  handleClick: function(event) {
    this.setState({ isAuthenticating: true });
  },
  render: function() {
    console.log(this.props.LoginRequest instanceof GitHubLoginRequest);
    var iconClass = classNames({
      'fa fa-5x': true,
      'fa-github-alt': !this.state.isAuthenticating,
      'fa-circle-o-notch fa-spin': this.state.isAuthenticating
    });
    var authUrl = this.props.LoginRequest.getAuthUrl();
    return (
    <Layout>
      <div className="jumbotron login">
        <h1 className="display-3">GitHub Goals</h1>
        <p className="lead">See stuff about your GitHub activity.</p>
        <hr className="m-y-2" />
        <a href={authUrl} className="btn btn-lg btn-primary-outline" onClick={this.handleClick}>
          <div><i className={iconClass}></i></div>
          Authenticate with GitHub
        </a>
      </div>
    </Layout>
    );
  }
});

Notice I'm doing instanceof validation to make sure the right object is getting passed in props. Now this works totally fine server side, however on the client side (since react-engine serializes to JSON and then deserializes) LoginRequest becomes a simple object is no longer an instance of GitHubLoginRequest.

Am I overcomplicating things? And if I am, it still seems like the current implementation makes it impossible to pass a complex type to a component and still work server side (since in my example, I no longer have access to getAuthUrl. I'd like to hear peoples thoughts!

cryptic-mystic commented 8 years ago

Could something like this be used to restore an objects type information?

samsel commented 8 years ago

@TheCrow1213 are you planning to reuse the instance of GitHubLoginRequest elsewhere? If not, can;t you instantiate GitHubLoginRequest inside your Login view?

cryptic-mystic commented 8 years ago

@samsel yeah since I posted this question I've stuck to props that are easily (de)serializable :)

samsel commented 8 years ago

:+1: