Coder Social home page Coder Social logo

react.rb's Introduction

React.rb has been renamed to Reactrb and moved to https://github.com/reactrb

Why?

So that we can consistently use the name Reactrb everywhere - domain names, twitter, github repos etc.

Everything else remains the same (and gets better everyday thanks to our great contributers and users.)

react.rb's People

Contributors

ajjahn avatar catmando avatar fkchang avatar gitter-badger avatar jgaskins avatar josephgrossberg avatar maxdignan avatar wied03 avatar zetachang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react.rb's Issues

make example apps into standalone repos?

Just chatting on gitter, and realized it might be easier for people if the example apps each had their own repo, so you can just clone to example app, and away you go.

Not a big deal of course.

change define_state

I propose changing define_state to work like this:

define_state do |v1, v2, v3|
  v1 = "initial value"
  v2 = "some other initial value"
  # v3 never gets initialized
end

You can also do

define_state do |v1 = "foo", v2 = "bar"| end

which is very nice too.

This is possible after ruby 1.9 because you can get the list of parameter names for the block.

This syntax will work only if there are NO define_state parameter... i.e. define_state(:x) will continue to work as it does today.

I will be happy to implement this and do a pull request, I just want some feedback that this will be acceptable.

Cannot read property โ€˜firstChildโ€™ of undefined

I am getting this error.

The web says this is caused by having 2 different versions of React.

I have tried every way to make sure that I only have one version, and I am still getting this error.

It is happening on the second render to a component, IF I am using opal-rspec in the browser.

I do not believe this is happening unless I am running opal-rspec.

I have done some basics like putting a console.log statement at the start of the react.js (unminimized) file and according to that log react.js is only loading once.

I have also made sure that react-source is not in my gem file.

Any clues or things to try would be greatly appreciated.

API Wrapping Coverage

React

  • React.createClass - not valid, React.create_element automatically cache the component class
  • React.createElement
  • React.createFactory
  • React.render
  • React.unmountComponentAtNode
  • React.renderToString
  • React.renderToStaticMarkup
  • React.isValidElement
  • React.DOM - use DOM builder DSL instead
  • React.PropTypes - refer to #4
  • React.initializeTouchEvents

React.Children (simply make children include Enumerable)

  • React.Children.map - map
  • React.Children.forEach - each
  • React.Children.count - length, size
  • React.Children.only - only (throw what??)

ReactComponent

  • setState - set_state(next_state)
  • replaceState set_state!(next_state)
  • forceUpdate force_update!
  • getDOMNode dom_node (maybe return opal-browser's Node)
  • isMounted
  • setProps set_props
  • replaceProps set_props!(next_props)

Component Spec

  • render
  • getInitialState - provided from define_state yielded result
  • getDefaultProps - refer to #4
  • propTypes - refer to #4
  • mixins
  • statics: use ruby class method
  • displayName

Component Lifecycle

  • componentWillMount - before_mount helpers
  • componentDidMount - after_mount helpers
  • componentWillReceiveProps - before_receive_props(next_props)
  • shouldComponentUpdate - needs_update?(next_props, next_state)
  • componentWillUpdate - before_update(next_props, next_state)
  • componentDidUpdate - after_update(prev_props, prev_state)
  • componentWillUnmount - before_unmount

react putting `<i>` tag around submit button

When I try to supply a class attribute to the submit button, an <i> tag magically appears around the button, it doesn't matter if I use the input helper or jsx , I've event tried this:

div( class_name: "input-field #{col 4}",dangerously_set_inner_HTML: { __html:
    '<input type="submit" value="Login" class="waves-effect waves-light btn waves-input-wrapper" />'
}.to_n)

I'm sure it's react because that tag only appears when I add a className, when I tried this with JSX, react messaged me saying that It didn't know what class was and that maybe I meant className so when I changed it the tag re-appeared.

Here's the HTML that gets generated:

<i class="waves-effect waves-light btn waves-input-wrapper waves-input-wrapper" style="">
    <input type="submit" value="Login" class="waves-button-input">
</i>

EDIT:
Further evidence, doing:

puts '<input type="submit" value="Login" class="waves-effect waves-light btn waves-input-wrapper" />'.to_n

results in

<input type="submit" value="Login" class="waves-effect waves-light btn waves-input-wrapper" />

Also, when trying to make a patch (using jquery to find the element and then change it) I did some puts, I found that the input was being almost correctly added, it was only missing .waves-button-input.
It's like it starts off how I want it, then during reacts rendering pass it changes it; first by pulling off the first class name, then takes the rest of it and sticks it in a wrapping <i> tag and then puts the first bit back in the class attribute of the input tag.

I had to add a sleep command so my jquery could find it after it had been fiddled with.

EDIT: I'm using the react-v0.13 branch.

Collision with Opal-JQuery

(discovered in pull request).

Another problem I'm seeing here is that react.rb ends up inadvertently defining a top level Element class (in addition to the React::Element class). This conflicts with opal-jquery and makes opal-jq pretty much unusable.

I added a test to try and verify this is fixed and I tried to format the js code in element.rb better. I'm not quite proficient enough in JS at the moment to understand what that code is doing, but it looks like you're cleverly trying to make the React Element objects that React itself produces inherit from this class. This just seems to be a side effect.

A simpler way (I think) to see this problem is to compile the following:

class User
  attr_accessor :joe
  def initialize
    @joe = 'howdy'
  end
end

module Mod
  class User < %x{
    (function() {
      var f = function() {};
      f.prototype = Object.getPrototypeOf(String);
      return f;
    })()
  }
    def other_method
      'nope'
    end
  end
end

puts User.new.joe

Warning on setting props.onEventName of React component

Warning: Don't set .props.onClick of the React component <input />. Instead, specify the correct value when initially creating the element. The element was created by TodoItem.

Reason

If you are on React.js v0.13, you might see this warning, since upon 0.13, props will be immutable.

Solution

To make the syntax on(:event_name) still work. We will shift to React.cloneElement (https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement).

with on(:click) react event can't access standard DOM methods

`
class Sample
include React::Component
define_state(:comments){
["foo", "bar"]
}

def handle_that(e)
p e.target.data('index') <----this not working
end

def render
div {
self.comments.each_with_index do |comment, index|
p("data-index" => index.to_s) { comment }.on(:click) { |e| handle_that(e) }
end
}
end
end
`

p e in handle_that returns Ract::Event object, p e.target returns Native paragraph object, but any other methods on p.target return "" or undefined, is it possible to access that target html, data attrs and so on? opal-browser and everything else is ok (using with rails).

Reactive-ruby state observers not working correctly

foo!.send(...method.., ...args..) should apply method to the value of foo, then signal that foo's internal state has changed.

What is actually happening is the value of foo is being set to the result of the method call. This works fine as long as the method returns the new value of foo. I.e. foo! << 'new item' works fine but things breaks if you do foo!.delete('item').

If you want to update the value of foo the syntax is foo! 'new value'

This may be a breaking change if anybody is counting on this behavior, but it is incorrect, and I want to get this fixed asap before people start depending on the misbehavior.

Add gitter.im badge

I think this would be very useful in promoting react.rb. Could we do this?

render should not fail silently

It would be a big help with debug if render would not fail silently, but instead simply print the exception raised etc.

Perhaps this is some setting in reactjs? Otherwise I am thinking that we could add a method render_debug to the component class, which calls render and prints any error message.

render_debug would be called by the API if it was available AND some kind of config switch was set.

how to get react.js source included?

I am working with the 0.8 opal branch
it does not include react-source (except in development)

The only way I can see to get react.js loaded is to include it in the index.html file?

Am I missing something?

Over on the opal gitter.im board, they figured you had a plan :-)

How robust is this?

I'm curious how well can this integrate with the typical frameworks. For example, will this work inside apps that incorporate many frameworks (e.g animation.css, bootstrap.css, highcharts.js) inside their application.

Are there any examples of large enterprises using this in their rails app?

Let me know!

error if component is not required

Say you do this:

React.render(React.create_element(MyFatComponent), Element['div.navigation'])

and you forget to require 'my_fat_component' Nothing happens, and there are no errors or warnings.

Instead the create_element binding (and similar) should make sure the constant does exist and responds to render.

Benefit to using React.createClass ?

I admittedly don't have an in depth understanding of exactly how react.rb maps to the underlying JS code, but would there be benefit in "caching" a Ruby/Opal class that includes React::Component such that https://github.com/facebook/react/blob/v0.13.1/src/classic/class/ReactClass.js is used?

It looks like, from the React code, there are some items it gets out of the way that might be nice for performance if a given component is used in several places.

That said, that would not play well with the monkey patching "feature" of Ruby

Maybe just calling createClass the first time someone tries to use a class and then holding on to that (e.g. in top_level.rb/create_element)?

[discuss] React Native Support

React Native for iOS is released yesterday!

To integrating with Opal Ruby tool chains, providing a packager API compatible version of our own may be a start point.

I haven't started to work on it, so feel free to leave any suggestions on possible direction! ๐Ÿ˜„

Upgrade to React v0.13

React.js v0.13 is released last month (http://facebook.github.io/react/blog/2015/03/10/react-v0.13.html).
Some work need to be done in react.rb to catch up this release, there is #17 which tracks all the changes introduced.

Depends on react-source

Previously , react-source gem v0.12.0 is only used as development dependency. Since the changes introduced will break in version under 0.13, so we will explicitly depends on react-source.

Also, you can now include the react source simply by adding a line as below without manually download or manage the source.

<%= javascript_include_tag 'react.js' %>

Toll-free bridge React::Component

We are introducing toll-free bridge React::Component.

Previously, the Ruby instance created through React.render(Foo) is actually not the component instance created by React.js framework. The Ruby instance is created during first mount and cached inside the actual component instance as a property.

Upgrading

All the DSL you got by include React::Component remains almost the same. Only difference is that previously the native ReactComponent will be passed as the first argument in the initializer of your class. But since the instance is actually the real ReactComponent instance. So simply refer to self in your initializer if you want to do stuff with it.

Other breaking changes

  • props are immutable now, so set_props & set_props! are deprecated, see official blog post for upgrading details.
  • set_state! are deprecated (since replaceState is deprecated , see original issue for more details)
  • dom_node is deprecated in favor of React.find_dom_node
  • React.find_dom_node return a plain DOM object rather than a Native

I will move all the details to wiki when this is actually done, and feel free to leave a comment if there is any concern or clarification needed. ๐Ÿ˜‰

isomorphic execution

Does this work?

There are two strategies I think:

  1. run opal on the server

  2. make a server version of react.rb that calls through to JS

  3. would be faster but more maintenance

[discuss/random] DOM2React

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 ๐Ÿธ

Need a way to deal with objects changing state (i.e. arrays)

For example

define_state(:foo) { ['joe', 'fred'] }

def add_friend(friend) 
  foo << friend
end

This does not work as foo << friend updates the array object, but there is no way to know that the foo state has been updated.

I have implemented a couple of solutions, and am interested in which people would prefer:

  1. define foo! method that will return an object that wrap the current value of foo, and observe any changes to that object. So you can write
def add_friend(friend)
  foo! << friend
end
  1. define foo! method that simple does foo = foo to indicate a state change. This would return self so that the methods could be chained
def add_friend(friend)
  foo << friend; foo!
end

or

def add_friend(friend)
  foo << friend
ensure
  foo!.bar!
end

2b) In addition the Proc class can be updated so this works

lambda { |new_friend| foo << new_friend }.foo! 

Just looking for people's input, preferences, or other ideas!

change name space

I keep running in to problems becuase react.rb is using the same name as react.js. Just crashed into this again trying to integrate with react-rails.

I suggest the file name be changed to opal-react (consistent with opal-jquery etc.) Module name can stay React.

I have tried this on my WIP branch, and it works great. After changing the file names to be opal-react, I was able to integrate without any difficulty with react-rails.

Please let me know your thoughts on this, and how to proceed re: pull request etc, as I want to go ahead and get this fully integrated with react-rails asap.

Tests?

I see a ton of commits on the reactive_ruby branch without any changes to tests. Does this project intend to go back in a more "test driven development" direction?

how to render children in dsl?

Its not clear (or perhaps there is no way) to render children in the DSL.

For example

class ReverseDiv
  render
    div do
      params[:children].reverse.each do |child|
        # what do I do here? 
      end
   end
end

With React::Component, calling "#on" on nested Elements throws away the callbacks (0.13)

This is due to rendering using blocks to define layouts and @buffer on method_missing. When evaluating those blocks, Elements will be created by recursively calling into the blocks, sharing a top-level array to gather the results. With a layout like:

def render
  button(type: "button").on(:click) do
    puts "Everybody say yeah!"
  end
end

the events are bound correctly because render will evaluate to what's returned by Element#on. However, doing it like this:

def render
  div do
    button(type: "button").on(:click) do
      puts "Everybody say yeah!"
    end
  end
end

Will ignore the button with the events, as it will latch onto the version inside the @buffer coming from div (i.e., the button WITHOUT the events).

If I understand correctly, using that buffer is just a way to collect what's rendered in nested blocks and finally render the topmost structure using React.create_element. Are the maintainers looking into this? Would it be ok to try and fix it?

React::Event 's target can't be turned to Opal Jquery Element

class Sample
  include React::Component
  define_state(:comments){
    ["foo", "bar"]
  }

  def handle_that(e)
    x = e.target <------returns dom element
    x= Element.find(x)
    puts x.html <-------nil returned
  end

  def render
    div {
      self.comments.each_with_index do |comment, index|
        p("data-index" => index.to_s, id: "foo") { comment }.on(:click) { |e| handle_that(e) }
      end
    }
  end
end

But if you do e.g. x =document.getElementById; x= Element.find(x); puts x.html everything works.
Is it possible to instantiate react event's target element as Opal Jquery Element? e.native_event.target doesn't work either.

0.13 branch not working with opal 0.7.2

@zetachang @weid03 It seems like with opal 0.7.2 the 0.13 branch breaks where it is defining the component factory specifically ctor.prototype = klass._proto; klass._proto is undefined, I assume something changed in 0.7.2... do either of you know about this?

React Plugin integration

I would like to know how to integrate react plugins, like this becuase I can't see how to do so from your expansive documentation.

Example in reactive-ruby '/examples' throws console error

Actually two issues probably related to each other

I cloned the reactive-ruby branch and tried running the 'examples' example and had trouble, other examples seemed to work fine so I'm suspecting this has to do with the reactive-router dependency.

  1. At first webrick would not start up because it could not find 'reactive-router' dir.
    Then I cloned reactor-router repo, changed the dirname to 'reactive-router' and made sure it was in place where the gemfile was looking.
  2. Webrick starts up but then page doesn't load with console error:
    Uncaught RangeError: Maximum call stack size exceeded

Digging deeper the error seems to originate from this line:
return (Opal.defn(self, '$method_missing', TMP_6 = function(n, args) {var $zuper = $slice.call(arguments, 0);
var $a, $b, TMP_7, $c, self = this, $iter = TMP_6.$$p, block = $iter || nil, name = nil, node_only = nil, e = nil, message = nil;
args = $slice.call(arguments, 1);

JSX equivalent?

Any plans for including a markup DSL like JSX?

To give this a Ruby flavor, maybe let users embed Haml or Slim markup?

explicit component naming does not work in reactive-ruby branch and a Readme error

  • This is from reactive-ruby branch * ref. catmando conversation of 8/22 details as requested in gitter

I had an issue following the readme to get this working ...

  1. First, comparing to the examples/rails_tutorials ... the component is named app/components/home.rb in the readme - but i could only get it to work if the component was in app/components/home/show.rb since the example component's name is Components::Home::Show ...
  2. The implicit naming did not work when using render_component in the home_controller.rb - which i am pretty sure is because the component's class was Components::Home::Show and not home
  3. I did get it to work using this explicit render call in the controller :
render inline: "<%= react_component 'Components::Home::Show', @rails_react_variables, { prerender: true} %>", layout: 'application'

and it worked correctly with prerender as both true and false.

  1. Side additional piece: @catmando identified an issue with explicit naming, too ... mentioning it here because my initial attempt was to use the helper as in :
render_component :hometest

where hometest (rather than home or home/show or whatever it needs to be !) was the component name and that varied from the controller name ... this is a common requirement where i want to reuse toplevel components from different controllers ....

  1. Last part is a suggestion ... at least for the readme ... even though reactive-ruby can find the components via autoloading ...it would help new users of the gem if the readme referenced the app/views/components/home/show.rb 1:1 mapping between component name and component source directory ....

Remove JSX support

After discussing with @catmando, to support JSX, extra dependency on sprockets make it hard to maintain backward compatibility either for opal 0.7 or rails 3.

And given that the integration with react-rails gem is possible, we could simply rely on JSX compiling feature provided by it rather than rolling our own.

reactive-ruby branch: set_state and =state seem to work in unexpected way

Looks like self.state[:foo] and self.foo (after define_state(:foo){"bar"}) live as different variables:
let:

class Show
      include React::Component 
      define_state(:liked) {"NO"}
      def render 
        div do     
          p do
            "#{liked}"
          end
          p do
            "click me"
          end.on(:click){
            handle_click
          }
        end
      end
      def handle_click
        self.liked = "yes"
        alert self.state[:liked]
      end     
end

would behave as expected.

BUT:

if in render you'll pass #{self.state[:liked]}, and in handle_click you'll use self.set_state(liked: "YES"),
on initial load it'll render nil instead of NO , but after on_handle it'l show "YES"
And it leads to following:
when you define_state(:foo) {"something"}, you are expecting that state[:foo] are the same things, but looks like they live in different places.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.