Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improper 'this' context during createClass(): 0.11.1 #2183

Closed
lwhorton opened this issue Sep 12, 2014 · 3 comments
Closed

Improper 'this' context during createClass(): 0.11.1 #2183

lwhorton opened this issue Sep 12, 2014 · 3 comments

Comments

@lwhorton
Copy link

In React 0.10, I am able to decorate the render method with a static render that returns a promise, as opposed to React's own callback implementation.

mixinRender = function(spec) {
    var statics
    spec.statics = statics = (spec.statics || {})
    // spot weld a static 'render' method with a .then()
    statics.render = statics.render || staticRenderFactory.call(this,spec)
    return spec
}

function staticRenderFactory(spec) {
    return function staticRender(model, node) {
        var promisified = Promise.promisify(React.renderComponent, React)

        var node = (node || spec.node(model))
        var Ctor = this(model) // <- this during runtime refers to the createClass() function
        return promisified(Ctor, node)
    }
}

This semi-decoration worked well enough for my purposes. It returns to the caller a descriptor as I would expect.

createClass: function(spec) {
    var Constructor = function() {};
    Constructor.prototype = new ReactCompositeComponentBase();
    Constructor.prototype.constructor = Constructor;

    var DescriptorConstructor = Constructor;

    var ConvenienceConstructor = function(props, children) {
      var descriptor = new DescriptorConstructor();
      descriptor.construct.apply(descriptor, arguments);
      return descriptor; // <- tada!
    };

However, following the same pattern in 0.11.1 gives me a no property 'construct error during the internal createClass() call.

Digging around in the codebase, it just looks like a forgotten context bind.

  createClass: function(spec) {
    var Constructor = function(props, owner) {
      this.construct(props, owner); // <- this is undefined, and hence construct is undefined
    };
    Constructor.prototype = new ReactCompositeComponentBase();
    Constructor.prototype.constructor = Constructor;
@zpao
Copy link
Member

zpao commented Sep 13, 2014

We do different wrapping around Constructor in 0.11 than we did in 0.10 so you probably need to adjust for that. You're hacking the system in unsupported ways so I don't think we have any intention of supporting your case directly.

cc @sebmarkbage in case he has anything to add / wants to reopen / think about things

@zpao zpao closed this as completed Sep 13, 2014
@lwhorton
Copy link
Author

I guess the real question is: "how do you create a component programmatically (from outside React's world)"?
For anyone who might look for this at a future point, here is a solution...

var descriptor = React.createClass.call(React, spec)
mixinRender(spec, descriptor)

function mixinRender(spec, descriptor) {
  Object.defineProperty(descriptor, 'render', {
    ... etc
    , value: function staticRender(model, node) {
      var Ctor = this(model)
      var component = React.renderComponent(Ctor, node)
      return Promise.resolve(component)
    }
  }
}

This just spot-welds a render onto the descriptor, the function that expects to receive props/children during a <SomeComponent someProp={...}> call. You are then allowed to call render(someModel, someNode). The component instance will be resolved, rendered, and returned with a promise API.

@sebmarkbage
Copy link
Collaborator

Basically you can just replace the line:

var Ctor = this(model);

with

var Ctor = React.createElement(this, model);

(note that this was called createDescriptor in 0.11.1 but will be called createElement in 0.11.2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants