zetachang / react.rb

Opal Ruby wrapper of React.js library.
http://reactrb.org/
MIT License
547 stars 35 forks source link

[discuss/random] DOM2React #13

Open elia opened 9 years ago

elia commented 9 years ago

Did a quick experiment about creating react elements out of living DOM, here's the code:

https://gist.github.com/elia/fad23026831a817e3526

I'd like to hear opinions, not sure if this can be useful, but the initial idea was to render static dom and do progressive enhancement through react instead of jquery.

The other idea I'd like to bring to the table is haml2react.rb, kinda on the lines of the Glimmer engine that will come to next Ember version, that's probably a better idea :)

PS. sorry for opening an issue, not probably the best place for a discussion, but I though gitter would have been to sync, and I don't want to miss a single comment on this :frog:

zetachang commented 9 years ago

Looks like a cool idea (also learn some cool tricks from your code :smile: ), would you mind explaining more on the haml2react.rb part?

elia commented 9 years ago

Would be cool to replace jsx with haml, I know they feel strongly about keeping the dom declaration along with the component code but you know, ppl like haml :stuck_out_tongue_winking_eye:

The point is that unlike parsing the living dom, haml clearly defines static and dynamic parts and the same object that are supplied to render the haml template can be used to render the react component

var HelloMessage = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

would be in haml (hello_message.haml)

%div
  Hello 
  = @name

plus:

class HelloMessage
  include React::Component
  # …
  def render
    ReactTemplate["hello_message"]
  end
end
adambeynon commented 9 years ago

@elia Another useful idea coming from the ember guys is that because they use a template language, rather than pure javascript, they are able to be clever about re-rendering. For example:

.some-class
  .some-other-class
    = some_value

From that template, when we re-render, we know that the only thing that could possibly change is the value passed from some_value, so we do not need to waste cpu cycles checking if .some_class or the inner class have changed - they never will.

Ember, using handlebars, are using this and getting some even better rendering speeds as static content never has to be re-checked between renders.

adambeynon commented 9 years ago

Sorry, I didn't explain that too well, but this does: https://github.com/emberjs/ember.js/pull/10501

zetachang commented 9 years ago

Just come up with idea to support different template language (erb, haml) by extending the DOM2React idea @elia present.

Basically every time the render method of the react component is called, the render method of the template language will be invoked which will return plain html back. And then we create an offscreen DOM tree (using innerHTML) and feed it to the DOM2React function which will construct the actual virtual DOM for us and used as the final return value.

We got the benefit of extensibility to all kind of template languages (which return html string as result) and still take advantage of React.js Virtual DOM technique to actually modify the on-screen DOM elements.

The only drawback may be the phase building the actual DOM tree, but since it's not even live on the screen, so all the expensive layouting and rendering will not actually happen.

elia commented 9 years ago

@adambeynon that's what I meant referring to ember's glimmer engine, actually I got the "inspiration " just after watching the ember 2015 keynote :shipit: :)

@zetachang not sure how expensive would be the offscreen rendering. Also that would give up the ability to pass data to the template. Probably if one wants to use ERB he'd be better off with JSX or HTMLBars directly.

zetachang commented 9 years ago

Actually the render method will work like pseudo code below,

def render
  offscreen_element = Element.create(Template['hello_message'].render(self))
  DOM2React.build(offscreen_element)
end

So it's still possible to pass data to the template rendering context.

elia commented 9 years ago

I see now, I still feel as it could defy react's performance gains. If js perf wasn't broken it would have been good to have a comparison there.

Another option could be to deep clone react elements and then mutate them, but I didn't seem to find anything on the subject yesterday … in that case tho the (possible) cost of rendering+parsing the Dom would be paid just once.

zerko commented 9 years ago

@adambeynon i believe that would add marginal performance increase, is it worth to leak abstractions to get it? Is this choice makes code cleaner? Could this be a problem for non-DOM targets? I dont know, but i personally like that React has no such assumptions built in.

Sorry for slight offtopic boys :)

sollycatprint commented 8 years ago

This issue was moved to reactrb/reactrb#13