Skip to content

Commit c5e884c

Browse files
committed
chore(docs) reorganize readme
1 parent dfb371f commit c5e884c

File tree

1 file changed

+107
-147
lines changed

1 file changed

+107
-147
lines changed

README.md

Lines changed: 107 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,17 @@
1313
1414
> ***Additionally: `0.x` branch directly follows React versions, `1.x` will not do so.***
1515
16-
react-rails is a ruby gem which makes it easier to use [React](http://facebook.github.io/react/) and [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) in your Ruby on Rails application.
16+
`react-rails` makes it easy to use [React](http://facebook.github.io/react/) and [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) in your Ruby on Rails (3.1+) application. `react-rails` can:
1717

18-
19-
1. Making it easy to include `react.js` as part of your dependencies in `application.js`.
20-
2. Transforming JSX into regular JS on request, or as part of asset precompilation.
21-
3. View helpers to render React components in an unobtrusive style and/or on the server.
18+
- Provide [various `react` builds](#reactjs-builds) to your asset bundle
19+
- Transform [`.jsx` in the asset pipeline](#jsx)
20+
- [Render components into views and mount them](#rendering--mounting) via view helper & `react_ujs`
21+
- [Render components server-side](#server-rendering) with `prerender: true`.
22+
- [Generate components](#component-generator) with a Rails generator
2223

2324
## Installation
2425

25-
We're specifically targeting versions of Ruby on Rails which make use of the asset pipeline, which means Rails 3.1+.
26-
27-
As with all gem dependencies, we strongly recommend adding `react-rails` to your `Gemfile` and using `bundler` to manage your application's dependencies.
26+
Add `react-rails` to your gemfile:
2827

2928
```ruby
3029
# Gemfile
@@ -44,39 +43,47 @@ This will require `react.js`, `react_ujs.js`, and a `components.js` manifest fil
4443

4544
## Usage
4645

47-
### react.js
46+
### React.js builds
4847

49-
In order to use React client-side in your application, you must make sure the browser requests it. One way to do that is to drop `react.js` into `vendor/assets/javascript/` and by default your application manifest will pick it up. There are downsides to this approach, so we made it even easier. Once you have `react-rails` installed, you can just add a line into your config file (see Configuring) and require react directly in your manifest:
48+
You can pick which React.js build (development, production, with or without [add-ons]((http://facebook.github.io/react/docs/addons.html))) to serve in each environment by adding a config. Here are the defaults:
5049

51-
You can `require` it in your manifest:
50+
```ruby
51+
# config/environments/development.rb
52+
MyApp::Application.configure do
53+
config.react.variant = :development
54+
end
5255

53-
```js
54-
// app/assets/javascripts/application.js
56+
# config/environments/production.rb
57+
MyApp::Application.configure do
58+
config.react.variant = :production
59+
end
60+
```
5561

56-
//= require react
62+
To include add-ons, use this config:
63+
64+
```ruby
65+
MyApp::Application.configure do
66+
config.react.addons = true # defaults to false
67+
end
5768
```
5869

59-
Alternatively, you can include it directly as a separate script tag:
70+
Then, you can include the requested build in your front-end by restarting your Rails server and adding `react` to your manifest:
6071

61-
```erb
62-
# app/views/layouts/application.html.erb
72+
```js
73+
// app/assets/javascripts/application.js
6374

64-
<%= javascript_include_tag "react" %>
75+
//= require react
6576
```
6677

67-
### JSX
78+
It will provide the build of React.js which was specified by the configurations.
6879

69-
To transform your JSX into JS, simply create `.js.jsx` files. These files will be transformed on request, or precompiled as part of the `assets:precompile` task.
80+
In a pinch, you can also provide your own copies of React.js and JSXTransformer. Just add `react.js` or `JSXTransformer.js` (case-sensitive) files to `app/vendor/assets/javascripts/react/` and restart your development server. If you need different versions of React in different environments, put them in directories that match `config.react.variant`. For example, if you set `config.react.variant = :development`, you could put a copy of `react.js` in `/vendor/assets/react/development/`.
7081

71-
CoffeeScript files can also be used, by creating `.js.jsx.coffee` files. We also need to embed JSX inside backticks so CoffeeScript ignores the syntax it doesn't understand. Here's an example:
82+
### JSX
7283

73-
```coffee
74-
Component = React.createClass
75-
render: ->
76-
`<ExampleComponent videos={this.props.videos} />`
77-
```
84+
After installing `react-rails`, restart your server. Now, `.js.jsx` files will be transformed in the asset pipeline.
7885

79-
You can use the `--harmony` or `--strip-types` options by adding a configuration to `application.rb`:
86+
You can use JSX `--harmony` or `--strip-types` options by adding a configuration:
8087

8188
```ruby
8289
config.react.jsx_transform_options = {
@@ -85,20 +92,17 @@ You can use the `--harmony` or `--strip-types` options by adding a configuration
8592
}
8693
```
8794

88-
### Unobtrusive JavaScript
95+
To use CoffeeScript, create `.js.jsx.coffee` files and embed JSX inside backticks, for example:
8996

90-
`react_ujs` will call `React.render` for every element with `data-react-class` attribute. React properties can be specified by `data-react-props` attribute in JSON format. For example:
91-
92-
```erb
93-
<!-- react_ujs will execute `React.render(HelloMessage({name:"Bob"}), element)` -->
94-
<div data-react-class="HelloMessage" data-react-props="<%= {name: 'Bob'}.to_json %>" />
97+
```coffee
98+
Component = React.createClass
99+
render: ->
100+
`<ExampleComponent videos={this.props.videos} />`
95101
```
96102

97-
`react_ujs` will also scan DOM elements and call `React.unmountComponentAtNode` on page unload. If you want to disable this behavior, remove `data-react-class` attribute in `componentDidMount`.
98-
99-
To use `react_ujs`, simply `require` it after `react` (and after `turbolinks` if [Turbolinks](https://github.com/rails/turbolinks) is used).
103+
### Rendering & mounting
100104

101-
**Note:** _Turbolinks >= 2.4.0 is recommended. For older versions `react_ujs` will disable the Turbolinks cache to ensure components are correctly unmounted. See [#87](https://github.com/reactjs/react-rails/issues/87) for details._
105+
`react-rails` includes a view helper (`react_component`) and an unobtrusive JavaScript (UJS) driver which work together to put React components on the page. You should require the UJS driver in your manifest after `react` (and after `turbolinks` if you use [Turbolinks](https://github.com/rails/turbolinks))
102106

103107
```js
104108
// app/assets/javascripts/application.js
@@ -108,122 +112,87 @@ To use `react_ujs`, simply `require` it after `react` (and after `turbolinks` if
108112
//= require react_ujs
109113
```
110114

111-
### View helper
112-
113-
There is a view helper method `react_component`. It is designed to work with `react_ujs` and takes a React class name, properties, and HTML options as arguments:
114-
115-
```ruby
116-
react_component('HelloMessage', name: 'John')
117-
# <div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}"></div>
118-
```
119-
120-
By default, a `<div>` element is used. Other tag and HTML attributes can be specified:
115+
The __view helper__ puts a `div` on the page with the requested component class & props. For example:
121116

122-
```ruby
123-
react_component('HelloMessage', {name: 'John'}, :span)
124-
# <span data-...></span>
125-
126-
react_component('HelloMessage', {name: 'John'}, {id: 'hello', class: 'foo', tag: :span})
127-
# <span class="foo" id="hello" data-...></span>
117+
```erb
118+
<%= react_component('HelloMessage', name: 'John') %>
119+
<!-- becomes: -->
120+
<div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}"></div>
128121
```
129122

130-
#### With JSON and Jbuilder
123+
On page load, the __`react_ujs` driver__ will scan the page and mount components using `data-react-class` and `data-react-props`. Before page unload, it will unmount components (if you want to disable this behavior, remove `data-react-class` attribute in `componentDidMount`).
131124

132-
You can pass prepared JSON directly to the helper, as well.
125+
`react_ujs` uses Turbolinks events if they're available, otherwise, it uses native events. __Turbolinks >= 2.4.0__ is recommended because it exposes better events.
133126

134-
```ruby
135-
react_component('HelloMessage', {name: 'John'}.to_json)
136-
# <div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}"></div>
137-
```
138-
139-
This is especially helpful if you are already using a tool like Jbuilder in your project.
127+
The view helper's signature is
140128

141129
```ruby
142-
# messages/show.json.jbuilder
143-
json.name name
130+
react_component(component_class_name, props={}, html_options={})
144131
```
145132

146-
```ruby
147-
react_component('HelloMessage', render(template: 'messages/show.json.jbuilder', locals: {name: 'John'}))
148-
# <div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}"></div>
149-
```
133+
- `component_class_name` is a string which names a globally-accessible component class. It may have dots (eg, `"MyApp.Header.MenuItem"`).
134+
- `props` is either an object that responds to `#to_json` or an already-stringified JSON object (eg, made with Jbuilder, see note below)
135+
- `html_options` may include:
136+
- `tag:` to use an element other than a `div` to embed `data-react-class` and `-props`.
137+
- `prerender: true` to render the component on the server.
138+
- `**other` Any other arguments (eg `class:`, `id:`) are passed through to [`content_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag).
150139

151-
##### Important Note
152140

153-
By default, the scaffolded Rails index Jbuilder templates do not include a root node. An example scaffolded index.json.jbuilder looks like this:
154141

155-
```ruby
156-
json.array!(@messages) do |message|
157-
json.extract! message, :id, :name
158-
json.url message_url(http://github.com/message,%20%3Cspan%20class=%22pl-c1%22%3Eformat:%3C/span%3E%20%3Cspan%20class=%22pl-c1%22%3E:json%3C/span%3E)
159-
end
160-
```
142+
### Server rendering
161143

162-
which generates JSON like this:
144+
To render components on the server, pass `prerender: true` to `react_component`:
163145

164-
```json
165-
[{"id":1,"name":"hello","url":"http://localhost:3000/messages/1.json"},{"id":2,"name":"hello","url":"http://localhost:3000/messages/2.json"},{"id":3,"name":"hello","url":"http://localhost:3000/messages/3.json"}]
166-
```
167-
168-
However ReactJS expects the collection of props provided to a component to be a key-value object. Therefore, if you want to use your Jbuilder templates directly with the helper, you will need to wrap your index.json.jbuilder array with a root node like so:
169-
170-
```ruby
171-
json.messages(@messages) do |message|
172-
json.extract! message, :id, :name
173-
json.url message_url(http://github.com/message,%20%3Cspan%20class=%22pl-c1%22%3Eformat:%3C/span%3E%20%3Cspan%20class=%22pl-c1%22%3E:json%3C/span%3E)
174-
end
146+
```erb
147+
<%= react_component('HelloMessage', {name: 'John'}, {prerender: true}) %>
148+
<!-- becomes: -->
149+
<div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}">
150+
<h1>Hello, John!</h1>
151+
</div>
175152
```
176153

177-
Which will generate:
154+
_(It will be also be mounted by the UJS on page load.)_
178155

179-
```json
180-
{"messages":[{"id":1,"name":"hello","url":"http://localhost:3000/messages/1.json"},{"id":2,"name":"hello","url":"http://localhost:3000/messages/2.json"},{"id":3,"name":"hello","url":"http://localhost:3000/messages/3.json"}]}
181-
```
156+
There are some requirements for this to work:
182157

183-
### Server Rendering
158+
- `react-rails` must load your code. By convention, it looks for a `assets/javascripts/components.js` file through the asset pipeline and loads that. This file must include your components _and_ their dependencies (eg, Underscore.js). For example:
184159

185-
React components can also use the same ExecJS mechanisms in Sprockets to execute JavaScript code on the server, and render React components to HTML to be delivered to the browser, and then the `react_ujs` script will cause the component to be mounted. In this way, users get fast initial page loads and search-engine-friendly pages.
160+
```js
161+
// app/assets/javascripts/components.js
162+
//= require_tree ./components
163+
// ^^ loads all files in `app/assets/javascripts/components/`
164+
```
165+
- Your components must be accessible in the global scope. If you are using `.js.jsx.coffee` files then the wrapper function needs to be taken into account:
186166

187-
#### ExecJS
167+
```coffee
168+
# @ is `window`:
169+
@Component = React.createClass
170+
render: ->
171+
`<ExampleComponent videos={this.props.videos} />`
172+
```
173+
- Your code can't reference `document`. Prerender processes don't have access to `document`, so jQuery and some other libs won't work in this environment :(
188174

189-
By default, ExecJS will use node.js in an external process to run JS code. Because we will be executing JS on the server in production, an in-process, high-performance JS VM should be used. Simply add the proper one for your platform to your Gemfile:
175+
You can configure your pool of JS virtual machines and specify where it should load code:
190176

191177
```ruby
192-
gem "therubyracer", :platforms => :ruby
193-
gem "therubyrhino", :platforms => :jruby
194-
```
195-
196-
#### components.js
197-
198-
In order for us to render your React components, we need to be able to find them and load them into the JS VM. By convention, we look for a `assets/javascripts/components.js` file through the asset pipeline, and load that. For example:
199-
200-
```sass
201-
// app/assets/javascripts/components.js
202-
//= require_tree ./components
203-
```
204-
205-
This will bring in all files located in the `app/assets/javascripts/components` directory. You can organize your code however you like, as long as a request for `/assets/javascripts/components.js` brings in a concatenated file containing all of your React components, and each one has to be available in the global scope (either `window` or `global` can be used). For `.js.jsx` files this is not a problem, but if you are using `.js.jsx.coffee` files then the wrapper function needs to be taken into account:
206-
207-
```coffee
208-
Component = React.createClass
209-
render: ->
210-
`<ExampleComponent videos={this.props.videos} />`
211-
212-
window.Component = Component
213-
```
214-
215-
#### View Helper
216-
217-
To take advantage of server rendering, use the same view helper `react_component`, and pass in `prerender: true` in the `options` hash.
218-
219-
```erb
220-
react_component('HelloMessage', {name: 'John'}, {prerender: true})
178+
# config/environments/application.rb
179+
# These are the defaults if you dont specify any yourself
180+
MyApp::Application.configure do
181+
# renderer pool size:
182+
config.react.max_renderers = 10
183+
# prerender timeout, in seconds:
184+
config.react.timeout = 20
185+
# where to get React.js source:
186+
config.react.react_js = lambda { File.read(::Rails.application.assets.resolve('react.js')) }
187+
# array of filenames that will be requested from the asset pipeline
188+
# and concatenated:
189+
config.react.component_filenames = ['components.js']
190+
end
221191
```
222-
This will return the fully rendered component markup, and as long as you have included the `react_ujs` script in your page, then the component will also be instantiated and mounted on the client.
223192

224-
### Component Generator
193+
### Component generator
225194

226-
react-rails ships with a Rails generator to help you get started with a simple component scaffold. You can run it using `rails generate react:component ComponentName`. The generator takes an optional list of arguments for default propTypes, which follow the conventions set in the [Reusable Components](http://facebook.github.io/react/docs/reusable-components.html) section of the React documentation.
195+
react-rails ships with a Rails generator to help you get started with a simple component scaffold. You can run it using `rails generate react:component ComponentName`. The generator takes an optional list of arguments for default propTypes, which follow the conventions set in the [Reusable Components](http://facebook.github.io/react/docs/reusable-components.html) section of the React documentation.
227196

228197
For example:
229198

@@ -276,31 +245,21 @@ The following additional arguments have special behavior:
276245

277246
Note that the arguments for `oneOf` and `oneOfType` must be enclosed in single quotes to prevent your terminal from expanding them into an argument list.
278247

279-
## Configuring
280-
281-
### Variants
248+
### Jbuilder & react-rails
282249

283-
There are 2 variants available. `:development` gives you the unminified version of React. This provides extra debugging and error prevention. `:production` gives you the minified version of React which strips out comments and helpful warnings, and minifies.
250+
If you use Jbuilder to pass JSON string to `react_component`, make sure your JSON is a stringified hash, not an array. This is not the Rails default -- you should add the root node yourself. For example:
284251

285252
```ruby
286-
# config/environments/development.rb
287-
MyApp::Application.configure do
288-
config.react.variant = :development
289-
end
290-
291-
# config/environments/production.rb
292-
MyApp::Application.configure do
293-
config.react.variant = :production
253+
# BAD: returns a stringified array
254+
json.array!(@messages) do |message|
255+
json.extract! message, :id, :name
256+
json.url message_url(http://github.com/message,%20%3Cspan%20class=%22pl-c1%22%3Eformat:%3C/span%3E%20%3Cspan%20class=%22pl-c1%22%3E:json%3C/span%3E)
294257
end
295-
```
296-
297-
### Add-ons
298-
299-
Beginning with React v0.5, there is another type of build. This build ships with some "add-ons" that might be useful - [take a look at the React documentation for details](http://facebook.github.io/react/docs/addons.html). In order to make these available, we've added another configuration (which defaults to `false`).
300258

301-
```ruby
302-
MyApp::Application.configure do
303-
config.react.addons = true
259+
# GOOD: returns a stringified hash
260+
json.messages(@messages) do |message|
261+
json.extract! message, :id, :name
262+
json.url message_url(http://github.com/message,%20%3Cspan%20class=%22pl-c1%22%3Eformat:%3C/span%3E%20%3Cspan%20class=%22pl-c1%22%3E:json%3C/span%3E)
304263
end
305264
```
306265

@@ -352,3 +311,4 @@ If you replace `JSXTransformer.js` in production environment, you have to restar
352311
because the jsx compiler context is cached.
353312

354313
Name of the `JSXTransformer.js` file *is case-sensitive*.
314+

0 commit comments

Comments
 (0)