| id | title | permalink | prev | next |
|---|---|---|---|---|
using-javascript-components |
Using Javascript Components |
using-javascript-components.html |
special-non-dom-attributes.html |
reconciliation.html |
While it is quite possible to develop large applications purely in Reactrb with a ruby back end like rails, you may eventually find you want to use some pre-existing React Javascript library. Or you may be working with an existing React-JS application, and want to just start adding some Reactrb components.
Either way you are going to need to import Javascript components into the Reactrb namespace. Reactrb provides both manual and automatic mechanisms to do this depending on the level of control you need.
Lets say you have an existing React Component written in javascript that you would like to access from Reactrb.
Here is a simple hello world component:
window.SayHello = React.createClass({
displayName: "SayHello",
render: function render() {
return React.createElement("div", null, "Hello ", this.props.name);
}
})Assuming that this component is loaded some place in your assets, you can then access this from Reactrb by creating a wrapper component:
class SayHello < React::Component::Base
imports 'SayHello'
end
class MyBigApp < React::Component::Base
def render
# SayHello will now act like any other Reactrb component
SayHello name: 'Matz'
end
endThe imports directive takes a string (or a symbol) and will simply evaluate it and check to make sure that the value looks like a React component, and then set the underlying native component to point to the imported component.
Many React components come in libraries. The ReactBootstrap library is one example. You can import the whole library at once using the React::NativeLibrary class. Assuming that you have initialized ReactBootstrap elsewhere, this is how you would bring it into Reactrb.
class RBS < React::NativeLibrary
imports 'ReactBootstrap'
endWe can now access our bootstrap components as components defined within the RBS scope:
# taken from Barrie Hadfield's excellent guide: http://tutorials.pluralsight.com/ruby-ruby-on-rails/reactrb-showcase
module Components
module Home
class Show < React::Component::Base
def say_hello(i)
alert "Hello from number #{i}"
end
render RBS::Navbar, bsStyle: :inverse do
RBS::Nav() do
RBS::NavbarBrand() do
a(href: '#') { 'Reactrb Showcase' }
end
RBS::NavDropdown(eventKey: 1, title: 'Things', id: :drop_down) do
(1..5).each do |n|
RBS::MenuItem(href: '#', key: n, eventKey: "1.#{n}") do
"Number #{n}"
end.on(:click) { say_hello(n) }
end
end
end
end
end
end
endBesides the imports directive, React::NativeLibrary also provides a rename directive that takes pairs in the form oldname => newname. For example:
rename 'NavDropdown' => 'NavDD', 'Navbar' => 'NavBar', 'NavbarBrand' => 'NavBarBrand'React::NativeLibrary will import components that may be deeply nested in the library. For example consider a component was defined as MyLibrary.MySubLibrary.MyComponent:
class MyLib < React::NativeLibrary
imports 'MyLibrary'
end
class App < React::NativeLibrary
def render
...
MyLib::MySubLibrary::MyComponent ...
...
end
endNote that the rename directive can be used to rename both components and sublibraries, giving you full control over the ruby names of the components and libraries.
If you use a lot of libraries and are using a Javascript tool chain with Webpack, having to import the libraries in both Reactrb and Webpack is redundant and just hard work.
Instead you can opt-in for auto importing Javascript components into Reactrb as you need them. Simply require react/auto-import immediately after you require reactrb.
For example typically you might have this:
# app/views/components.rb
require 'opal'
require 'reactrb'
require 'reactrb/auto-import' # this opts into auto-importing javascript components
if React::IsomorphicHelpers.on_opal_client?
require 'opal-jquery'
require 'browser'
require 'browser/interval'
require 'browser/delay'
end
require_tree './components'Now you do not have to use component imports directive or React::NativeLibrary unless you need to rename a component.
In Ruby all module and class names normally begin with an uppercase letter. However in Javascript this is not always the case, so the auto import will first try the Javascript name that exactly matches the Ruby name, and if that fails it will try the same name with the first character downcased. For example
MyComponent will first try MyComponent in the Javascript name space, then myComponent.
Likewise MyLib::MyComponent would match any of the following in the Javascript namespace: MyLib.MyComponent, myLib.MyComponent, MyLib.myComponent, myLib.myComponent
How it works: The first time Ruby hits a native library or component name, the constant value will not be defined. This will trigger a lookup in the javascript name space for the matching component or library name. This will generate either a new subclass of React::Component::Base or React::NativeLibrary that imports the javascript object, and no further lookups will be needed.
If you are in the business of importing components with a tool like Webpack, then you will need to let Webpack (or whatever dependency manager you are using) take care of including the React source code. Just make sure that you are not including it on the ruby side of things. Reactrb is currently tested with React versions 13, 14, and 15, so its not sensitive to the version you use.
However it gets a little tricky if you are using the react-rails gem. Each version of this gem depends on a specific version of React, and so you will need to manually declare this dependency in your Javascript dependency manager. Consult this table to determine which version of React you need. For example assuming you are using npm to install modules and you are using version 1.7.2 of react-rails you would say something like this:
npm install react@15.0.2 react-dom@15.0.2 --saveJust a word on Webpack: If you a Ruby developer who is new to using Javascript libraries then we recommend using Webpack to manage javascript component dependencies. Webpack is essentially bundler for Javascript. Barrie Hadfield has put together a very nice tutorial to get you started here.
There are also good tutorials on integrating Webpack with existing rails apps a google search away.