2016-05-12 dcrug react.rb
TRANSCRIPT
JavaScript!
CoffeeScript
ClojureScript
TypeScript
Elm
Flow
Opal
Compiles Ruby-like language to JS
Question #1: Is it Ruby?
Maximally tries to be Ruby
FAQ: How compatible is Opal?
We run opal against rubyspec as our primary testingsetup. We try to make Opal as compatible as possible,whilst also taking into account restrictions ofJavaScript when applicable. Opal supports themajority of ruby syntax features, as well as a verylarge part of the corelib implementation. We supportmethod_missing, modules, classes, instance_exec,blocks, procs and lots lots more. Opal can compileand run Rspec unmodified, as well as self hosting thecompiler at runtime.
In Other Words:
Kinda. Mostly. Lots!
Question #2: Is it horribly slow?
Key semantic differences:
· Numbers are JS floats· Symbol == String, are immutable· No threads· No frozen objects· No private/protected
"foo" # => "foo", class String < React::Component::Base:foo # => "foo", class String < React::Component::Base
42 # => 42, class Numeric < React::Component::Base3.141 # => 3.142, class Numeric < React::Component::Base5.to_r # Error: undefined method (next ver!)
# Ruby->JS integration
`window.title` # => window.title
%x{ console.log("opal version is: #{ RUBY_ENGINE_VERSION }");}
puts "opal version is: #{ RUBY_ENGINE_VERSION }"
// JS->Ruby integration
Opal.Foo.$new().$hello()
# One source of slowdown:# In Ruby, and thus in Opal...
6 * 7
# ...is really...
6.send(:+, 7)
So far... haven't noticed any speed difference.
Question #3: Does it actually work?
(DEMO Opal IRB)
http://fkchang.github.io/opal-irb/index-jq.html
Works For Me!™
Question #4: Can you debug it?
Er... next question please.
(haha. But seriously, during demos wedebug some things without issue!)
Question #5: Oookkkkaayy?
Volt - Client and Server
Clearwater - Client
React.rb - Client
Components
class Greeting < React::Component::Base def render div { "Hello!" } endend
Document.ready? do React.render( React.create_element(Greeting), Element['#content'] )end
<html> <head> <title>Inline Reactive Ruby Demo</title> <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <script src="inline-reactive-ruby.js"></script>
<!-- scripts can be remote or inline --> <script type="text/ruby"> puts "Hello!" </script>
<!-- scripts can be remote or inline --> <script type="text/ruby" src="hello.rb"></script>
</head> <body> <div id="content"></div> </body></html>
Nested Components
class GreetApp < React::Component::Base def render Greeting {} endend
class Greeting < React::Component::Base def render div { "Hello!" } endend
Component params
class GreetApp < React::Component::Base def render Greeting(name: "Friend") endend
class Greeting < React::Component::Base param :name
def render div { "Hello, #{params.name}!" } endend
Component state
class GreetApp < React::Component::Base define_state :name { "Friend" }
def render div { span { "Name: " } input(value: state.name).on(:change) { |e| state.name! e.target.value }
Greeting(name: state.name) } endend
class Greeting < React::Component::Base param :name
def render div { "Hello, #{params.name}!" } endend
Lifecycle events
before_mountafter_mountbefore_receive_propsbefore_updateafter_updatebefore_unmount
class GreetApp < React::Component::Base define_state :name
before_mount do state.name! "Friend" end
def render div { span { "Name: " } input(value: state.name).on(:change) { |e| state.name! e.target.value }
Greeting(name: state.name) } endend
class Greeting < React::Component::Base param :name
def render div { "Hello, #{params.name}!" } endend
Callbacks for bubbling upstate changes
class GreetApp < React::Component::Base define_state :name
before_mount do state.name! "Friend" end
def render div { span { "Name: " } input(value: state.name).on(:change) { |e| state.name! e.target.value }
Greeting(name: state.name, clear_name: lambda { state.name! "" }) } end
end
class Greeting < React::Component::Base param :name param :clear_name, type: Proc
def render div { span { "Hello, #{params.name}!" } a(href: '#') { "CLEAR" }.on(:click) { params.clear_name } } endend
(DEMO of inline-reactive-ruby)
Learning App:
White Elephant Gift Selector
(DEMO of WIP app)
BONUS: Feedback Loops, State, and You
Clojure
ClojureScript
Reagent
Figwheel
Amazing workflow!
(DEMO of liveloader)
References:
reactrb.org
inline-reactive-ruby
figwheel
Code for this:http://tinyurl.com/20160512-DCRUG-React-rb
WIP White Elephant App:https://github.com/awwaiid/reactrb-elephant