React.rb is an Opal Ruby wrapper of React.js library.
It lets you write reactive UI components, with Ruby's elegance using the tried and true React.js engine. ❤️
Visit Our Documentation Site For The Full Story
Reactive Ruby started as a fork of the original react.rb gem, and has since been merged back into react.rb's master branch. It aims to take react.rb a few steps further by embracing it's 'Ruby-ness'.
Reactive-Ruby is maturing, but is still a work in progress. Currently it is being used in a large rails app. However the gem itself has no dependency on rails, and there are people using the gem in other environments.
Stable react.rb can be found in the 0-3-stable branch.
A react app is built from one or more trees of components. React components can live side by side with other non-react html and javascript. A react component is just like a rails view or a partial. Reactive-Ruby takes advantage of these features by letting you add Reactive-Ruby components as views, and call them directly from your controller like any other view.
By design Reactive-Ruby allows reactive components to be easily added to existing Rails projects, as well in new development.
Components are first rendered to HTML on the server (called pre-rendering) this is no different from what happens when your ERB or HAML templates are translated to HTML.
A copy of the react engine, and your components follows the rendered HTML to the browser, and then when a user interacts with the page, it is updated on the client.
The beauty is you now have one markup description, written in the same language as your server code, that works both as the HTML template and as an interactive component.
See the wiki for more details.
In your Gemfile:
gem 'reactive-ruby'
gem 'react-rails', '~> 1.3.2'
gem 'opal-rails', '~> 0.8.1'
gem 'therubyracer', platforms: :ruby # Required for prerendering
# for JRuby you need the below line instead
# gem 'therubyrhino, platforms: :jruby
Run bundle install
and restart your rails server.
Your react components will go into the app/views/components/
directory of your
rails app.
Within your app/views
directory you need to create a components.rb
manifest.
Files required in app/views/components.rb
will be made available to the server
side rendering system as well as the browser.
# app/views/components.rb
require 'opal'
require 'reactive-ruby'
require_tree './components'
In assets/javascript/application.rb
require your components manifest as well
as any additional browser only assets.
# assets/javascript/application.rb
# Require files that are browser side only.
# Make components available by requiring your components.rb manifest.
require 'components'
# 'react_ujs' tells react in the browser to mount rendered components.
require 'react_ujs'
# Finally, require your other javascript assets. jQuery for example...
require 'jquery' # You need both these files to access jQuery from Opal.
require 'opal-jquery' # They must be in this order.
Components may be rendered directly from a controller action by simply following
a naming convention. To render a component from the home#show
action, create a
component class named Show
. For details on how to override this behavior, and how the the module tree is searched for
the class see the next section.
# app/views/components/home/show.rb
module Components
module Home
class Show
include React::Component # will create a new component named Show
optional_param :say_hello_to
def render
puts "Rendering my first component!"
# render "hello" with optional 'say_hello_to' param
"hello #{say_hello_to if say_hello_to}"
end
end
end
end
Call render_component
in the controller action passing in any params (React
props), to render the component:
# controllers/home_controller.rb
class HomeController < ApplicationController
def show
# render_component uses the controller name to find the 'show' component.
render_component say_hello_to: params[:say_hello_to]
end
end
Make sure your routes file has a route to your home#show action. Visit that route in your browser and you should see 'Hello' rendered.
Open up the js console in the browser and you will see a log showing what went on during rendering.
Have a look at the sources in the console, and notice your ruby code is there, and you can set break points etc.
You can control the top level component name and search path.
By default the component class name is inferred from the controller method rendering the component.
You can also specify the component name explicitly in the render_component
method.
render_component "Blatz
will search the for a component class named Blatz
regardless of the name of the controller method.
Searching for components works like this: Given a controller named
"Foo" then react.rb will search for a module named Foo
containing the component.
If this fails all modules will be searched (i.e. the name of the controller will be
ignored.) In either case the search begins at the outer most scope until a match is made.
Thus for example given a controller named Foo
, components could be found in the Foo
module,
the Components::Foo
module, in the outer most scope, or in any nested module.
The way the search works allows for small projects that do not need a lot
of name spacing, and also allows components to be shared across several controllers.
Saying render_component "::Blatz"
will only search the outer scope, while
"::Bar::Blatz"
will look only in the module Bar
for a class named Blatz
.
See the sinatra example.
Sometimes it may be necessary to run code only on the server or only in the browser. To execute code only during server side rendering:
if React::IsomorphicHelpers.on_opal_server?
puts 'Hello from the server'
end
To execute code only in the browser:
if React::IsomorphicHelpers.on_opal_client?
puts 'Hello from the browser'
end
Uncaught TypeError: Cannot read property 'toUpperCase' of undefined
This
means the thing you are trying to render is not actually a react component.
Often is because the top level component name is wrong. For example if you are
in controller Foo and the method is bar
, but you have named the component
Foo::Bars then you would see this message.
Sometimes its handy to switch off prerendering. Add ?no_prerender=1
... to
your url.
- Documentation
- Should load the RubyRacer, or at least report an error if the RubyRacer is not present
- Get everything to autoload what it needs (i.e. much less config setup)
To run the above examples project yourself:
git clone
the projectcd example/tutorial
bundle install
bundle exec rackup
- Open
http://localhost
- Run
bundle exec rake test_app
to generate a dummy test app. bundle exec rake
This project is still in early stage, so discussion, bug report and PR are really welcome 😉. We check in often at https://gitter.im/zetachang/react.rb ask for @catmando as David is on leave right now.
We check in often at https://gitter.im/zetachang/react.rb ask for @catmando.
In short, React.rb is available under the MIT license. See the LICENSE file for more info.