react-rails 3.1.1 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e21548e44de86710093640f1ec4b9fb7894a240d7f908cabcc9a6a0c271826dc
4
- data.tar.gz: 5879119b9a1c41c818896a82fc6b3596119e46b286eab96a54ad8489c803db5f
3
+ metadata.gz: 0e07b2e5987c055d954ae6a4e454d82f5604f9b3d1f65ee836a0964cc76ddfc8
4
+ data.tar.gz: 6689198dab8f72b32cc88727a21fc8635877f0ab0e2a8cb1a2058947615db3fb
5
5
  SHA512:
6
- metadata.gz: dd4903039cd95c518f5b6cb9e5021711693cd0cca1a251d00957e5b03df88d87e5c2c57e1f1f6fbc24bf1d9553d8d23523c1f33caaa218e2953e5124e27874a5
7
- data.tar.gz: 830bf9d620edcc4084e88f330aa30a7f091cb56eed48d17bd7ca302878c912fa3ccead712bde0ba27369dad9d4e3768d5f28b564ac596672b8ec98bdbc2f2002
6
+ metadata.gz: ee7710e9956cb049e915968ab1ce1ffa18daa58390506b7196308d5787a0903f8a1c24c16e4aff35ab1b086056c94df6c13675c6dc8d519928cbcc972c8b2f2c
7
+ data.tar.gz: 683311b4496260d2d88e6a1db75ece5178181d186d855884752b9cd5da885203aa45392c952ca4e5f2b3e5234a437912a32848aaf0292cdb93340881f5e11458
data/CHANGELOG.md CHANGED
@@ -1,13 +1,29 @@
1
1
  # react-rails
2
2
 
3
- If you need help upgrading `react-rails`, `webpacker` to `shakapacker`, or JS packages, contact justin@shakacode.com. The ShakaCode.com team is helping to maintain this Ruby gem. You also might want to consider the [react_on_rails](https://github.com/shakacode/react_on_rails) gem.
3
+ If you need help upgrading `react-rails`, `webpacker` to `shakapacker`, or JS packages, contact justin@shakacode.com. The ShakaCode.com team is helping to maintain this Ruby gem. You also might want to consider the [react_on_rails](https://github.com/shakacode/react_on_rails) gem.
4
4
 
5
5
  [#1209 2.7 Release Discussion](https://github.com/reactjs/react-rails/issues/1209)
6
6
 
7
7
  ## Unreleased
8
8
  Changes since the last non-beta release.
9
9
 
10
- _Please add entries here for your pull requests that are not yet released._
10
+ _Please add entries here for your pull requests that are not yet released. Include LINKS for PRs and committers._
11
+
12
+ #### Fixed
13
+ - Replaced call to ReactRailsUJS.unmountComponents that was erroneously removed by #1290 in 3.0.0 #1339
14
+
15
+ - Prevent roots from being re-created when using React 18 [PR 1305](https://github.com/reactjs/react-rails/pull/1305) by [diogobeda](https://github.com/diogobeda)
16
+
17
+ ## [3.2.0] - 2024-01-10
18
+
19
+ #### Changed
20
+ - Support other JS package managers using `package_json` gem [PR #1306](https://github.com/reactjs/react-rails/pull/1306) by [G-Rath](https://github.com/G-Rath).
21
+ - Make es6 and ts usable at same time. #1299
22
+
23
+ ## [3.1.1] - 2023-08-16
24
+
25
+ #### Removed
26
+ - Removed the replace-null functionality due a severe logic error added in 3.1.0 #1300
11
27
 
12
28
  ## [3.1.0] - 2023-08-15
13
29
 
@@ -17,7 +33,7 @@ _Please add entries here for your pull requests that are not yet released._
17
33
  ## [3.0.0] - 2023-08-14
18
34
 
19
35
  ### Breaking Changes
20
- - Requires separate compilations for server & client bundles if using Shakapacker (see [Webpack config](https://github.com/reactjs/react-rails/tree/master/test/dummy/config/webpack)) #1274
36
+ - Requires separate compilations for server & client bundles if using Shakapacker (see [Webpack config](https://github.com/reactjs/react-rails/tree/main/test/dummy/config/webpack)) #1274
21
37
  - Replaces WebpackManifestContainer, which searched for assets in the webpack manifest, with SeparateServerBundleContainer, which expects a single server bundle file & does not use the webpack manifest at all. #1274
22
38
  - Upgrades React-Rails' embedded react to v18.2.0. Uses node polyfill plugin & fast-text-encoder for SSR text encoding. #1290
23
39
  - If using Webpacker/Shakapacker, requires upgrading to Shakapacker v7 #1274 and #1285
@@ -562,7 +578,9 @@ _Please add entries here for your pull requests that are not yet released._
562
578
  - Server rendering with `prerender: true`
563
579
  - Transform `.jsx` in the asset pipeline
564
580
 
565
- [Unreleased]: https://github.com/reactjs/react-rails/compare/v3.1.0...master
581
+ [Unreleased]: https://github.com/reactjs/react-rails/compare/v3.2.0...main
582
+ [3.2.0]: https://github.com/reactjs/react-rails/compare/v3.1.1...v3.2.0
583
+ [3.1.1]: https://github.com/reactjs/react-rails/compare/v3.1.0...v3.1.1
566
584
  [3.1.0]: https://github.com/reactjs/react-rails/compare/v3.0.0...v3.1.0
567
585
  [3.0.0]: https://github.com/reactjs/react-rails/compare/v2.7.1...v3.0.0
568
586
  [2.7.1]: https://github.com/reactjs/react-rails/compare/v2.7.0...v2.7.1
data/README.md CHANGED
@@ -4,10 +4,7 @@
4
4
  [![npm](https://img.shields.io/npm/v/react_ujs.svg?style=flat-square)](https://www.npmjs.com/package/react_ujs)
5
5
  [![Ruby](https://github.com/reactjs/react-rails/actions/workflows/ruby.yml/badge.svg)](https://github.com/reactjs/react-rails/actions/workflows/ruby.yml)
6
6
 
7
- ## News
8
- V3.0.0 is released with Shakapacker v6 support, including SSR. Please try it out and report any issues. We'll try to address any critical issues ASAP.
9
-
10
- For version 2.7 documentation checkout [2.7-stable](https://github.com/reactjs/react-rails/tree/2.7-stable) branch.
7
+ For version 2.7 documentation, visit the [2.7-stable](https://github.com/reactjs/react-rails/tree/2.7-stable) branch.
11
8
 
12
9
  ## Summary
13
10
  React-Rails is a flexible tool to use [React](http://facebook.github.io/react/) with Rails. The benefits:
@@ -16,12 +13,26 @@ React-Rails is a flexible tool to use [React](http://facebook.github.io/react/)
16
13
  * Supports Sprockets 4.x, 3.x
17
14
  * Lets you use [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html), [ES6](http://es6-features.org/), [TypeScript](https://www.typescriptlang.org/), [CoffeeScript](http://coffeescript.org/)
18
15
 
16
+ ---
17
+
18
+ While ShakaCode will continue to support this gem, you might consider migrating to [React on Rails](https://github.com/shakacode/react_on_rails) or [React on Rails Pro with proper Node rendering](https://www.shakacode.com/react-on-rails-pro/).
19
+
20
+ Why? React on Rails code receives much more active development and testing. For example, consider the [ReactRailsUJS](https://github.com/reactjs/react-rails/blob/master/react_ujs/index.js) implementation compared to the [ReactOnRails Node package](https://github.com/shakacode/react_on_rails/tree/master/node_package) which is written in TypeScript. For another example, React on Rails has work underway to support the latest React features, such as [React Server Components](https://react.dev/reference/rsc/server-components).
21
+
22
+ You can find [migration to React on Rails steps here](https://github.com/reactjs/react-rails/blob/master/docs/migrating-from-react-rails-to-react_on_rails.md).
23
+
19
24
  ---
20
25
  ## ShakaCode Support
21
26
 
22
- [ShakaCode](https://www.shakacode.com) offers support for upgrading this gem, and related gems such as Webpacker and using Shakapacker. If interested, contact Justin Gordon, [justin@shakacode.com](mailto:justin@shakacode.com). We're also [hiring](https://jobs.lever.co/shakacode/3bdbfdb3-4495-4611-a279-01dddb351abe)!
27
+ [ShakaCode](https://www.shakacode.com) focuses on helping Ruby on Rails teams use React and Webpack better. We can upgrade your project and improve your development and customer experiences, allowing you to focus on building new features or fixing bugs instead.
28
+
29
+ For an overview of working with us, see our [Client Engagement Model](https://www.shakacode.com/blog/client-engagement-model/) article and [how we bill for time](https://www.shakacode.com/blog/shortcut-jira-trello-github-toggl-time-and-task-tracking/).
30
+
31
+ We also specialize in helping development teams lower infrastructure and CI costs. Check out our project [Control Plane Flow](https://github.com/shakacode/control-plane-flow/), which can allow you to get the ease of Heroku with the power of Kubernetes and big cost savings.
23
32
 
24
- Here's a testimonial of how ShakaCode can help, from [Florian Gößler](https://github.com/FGoessler) of [Blinkist](https://www.blinkist.com/), January 2, 2023:
33
+ If you think ShakaCode can help your project, [click here](https://meetings.hubspot.com/justingordon/30-minute-consultation) to book a call with [Justin Gordon](mailto:justin@shakacode.com), the creator of React on Rails and Shakapacker.
34
+
35
+ Here's a testimonial of how ShakaCode can help from [Florian Gößler](https://github.com/FGoessler) of [Blinkist](https://www.blinkist.com/), January 2, 2023:
25
36
  > Hey Justin 👋
26
37
  >
27
38
  > I just wanted to let you know that we today shipped the webpacker to shakapacker upgrades and it all seems to be running smoothly! Thanks again for all your support and your teams work! 😍
@@ -30,836 +41,71 @@ Here's a testimonial of how ShakaCode can help, from [Florian Gößler](https://
30
41
  >
31
42
  > Have a great 2023 and maybe we get to work together again later in the year! 🙌
32
43
 
33
- Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=date_DESC#review-2118154). Here's [another review of a Shakapacker migration that led to more work](https://clutch.co/profile/shakacode#reviews?sort_by=date_DESC#review-2096078).
44
+ Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=date_DESC#review-2118154).
34
45
 
35
46
  ## Resources
36
47
  * [Click to join **React + Rails Slack**](https://reactrails.slack.com/join/shared_invite/enQtNjY3NTczMjczNzYxLTlmYjdiZmY3MTVlMzU2YWE0OWM0MzNiZDI0MzdkZGFiZTFkYTFkOGVjODBmOWEyYWQ3MzA2NGE1YWJjNmVlMGE). Then join the channel `#react-rails`.
37
- * If you are upgrading, you might consider migrating to the [react_on_rails](https://github.com/shakacode/react_on_rails) gem.
48
+ * If upgrading, consider migrating to the [react_on_rails](https://github.com/shakacode/react_on_rails) gem.
38
49
  * Source code example utilizing React-Rails: https://github.com/BookOfGreg/react-rails-example-app
39
50
 
40
- <!-- START doctoc generated TOC please keep comment here to allow auto update -->
41
- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
42
- ## Contents
43
-
44
- - [Get started with Shakapacker](#get-started-with-shakapacker)
45
- - [Component name](#component-name)
46
- - [File naming](#file-naming)
47
- - [Typescript support](#typescript-support)
48
- - [Test component](#test-component)
49
- - [Use with Asset Pipeline](#use-with-asset-pipeline)
50
- - [Custom JSX Transformer](#custom-jsx-transformer)
51
- - [Transform Plugin Options](#transform-plugin-options)
52
- - [React.js versions](#reactjs-versions)
53
- - [View Helper](#view-helper)
54
- - [Custom View Helper](#custom-view-helper)
55
- - [UJS](#ujs)
56
- - [Mounting & Unmounting](#mounting--unmounting)
57
- - [Event Handling](#event-handling)
58
- - [`getConstructor`](#getconstructor)
59
- - [Server-Side Rendering](#server-side-rendering)
60
- - [Configuration](#configuration)
61
- - [JavaScript State](#javascript-state)
62
- - [Custom Server Renderer](#custom-server-renderer)
63
- - [Controller Actions](#controller-actions)
64
- - [Component Generator](#component-generator)
65
- - [Use with JBuilder](#use-with-jbuilder)
66
- - [Camelize Props](#camelize-props)
67
- - [Changing Component Templates](#changing-component-templates)
68
- - [Upgrading](#upgrading)
69
- - [2.7 to 3.0](#27-to-30)
70
- - [2.3 to 2.4](#23-to-24)
71
- - [Common Errors](#common-errors)
72
- - [Getting warning for `Can't resolve 'react-dom/client'` in React < 18](#getting-warning-for-cant-resolve-react-domclient-in-react--18)
73
- - [Undefined Set](#undefined-set)
74
- - [Using TheRubyRacer](#using-therubyracer)
75
- - [HMR](#hmr)
76
- - [Related Projects](#related-projects)
77
- - [Contributing](#contributing)
78
-
79
- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
80
-
81
-
82
- After reading this README file, additional information about React-Rails can be found in the Wiki page:
51
+ ## Documentation
52
+
53
+ - [Get started](docs/get-started.md)
54
+ - [Use with Shakapacker](docs/get-started.md#use-with-shakapacker)
55
+ - [Component name](docs/get-started.md#component-name)
56
+ - [File naming](docs/get-started.md#file-naming)
57
+ - [Typescript support](docs/get-started.md#typescript-support)
58
+ - [Test component](docs/get-started.md#test-component)
59
+ - [Use with Asset Pipeline](docs/get-started.md#use-with-asset-pipeline)
60
+ - [Custom JSX Transformer](docs/get-started.md#custom-jsx-transformer)
61
+ - [Transform Plugin Options](docs/get-started.md#transform-plugin-options)
62
+ - [React.js versions](docs/get-started.md#reactjs-versions)
63
+ - [View Helper](docs/view-helper.md)
64
+ - [Custom View Helper](docs/view-helper.md#custom-view-helper)
65
+ - [UJS](docs/ujs.md)
66
+ - [Mounting & Unmounting](docs/ujs.md#mounting--unmounting)
67
+ - [Event Handling](docs/ujs.md#event-handling)
68
+ - [`getConstructor`](docs/ujs.md#getconstructor)
69
+ - [Server-Side Rendering](docs/server-side-rendering.md)
70
+ - [Configuration](docs/server-side-rendering.md#configuration)
71
+ - [JavaScript State](docs/server-side-rendering.md#javascript-state)
72
+ - [Custom Server Renderer](docs/server-side-rendering.md#custom-server-renderer)
73
+ - [Controller Actions](docs/controller-actions.md)
74
+ - [Component Generator](docs/component-generator.md)
75
+ - [Use with JBuilder](docs/component-generator.md#use-with-jbuilder)
76
+ - [Camelize Props](docs/component-generator.md#camelize-props)
77
+ - [Changing Component Templates](docs/component-generator.md#changing-component-templates)
78
+ - [Upgrading](docs/upgrading.md)
79
+ - [2.7 to 3.0](docs/upgrading.md#27-to-30)
80
+ - [2.3 to 2.4](docs/upgrading.md#23-to-24)
81
+ - [Migrating from `react-rails` to `react_on_rails`](docs/migrating-from-react-rails-to-react_on_rails.md)
82
+ - [Why migrate?](docs/migrating-from-react-rails-to-react_on_rails.md#why-migrate)
83
+ - [Steps to migrate](docs/migrating-from-react-rails-to-react_on_rails.md#steps-to-migrate)
84
+ - [Common Errors](docs/common-errors.md)
85
+ - [Getting warning for `Can't resolve 'react-dom/client'` in React < 18](docs/common-errors.md#getting-warning-for-cant-resolve-react-domclient-in-react--18)
86
+ - [Undefined Set](docs/common-errors.md#undefined-set)
87
+ - [Using TheRubyRacer](docs/common-errors.md#using-therubyracer)
88
+ - [HMR](docs/common-errors.md#hmr)
89
+ - [Tests in component directory](docs/common-errors.md#tests-in-component-directory)
90
+
91
+ After reading this README file, additional information about React-Rails can be found on the Wiki page:
83
92
  https://github.com/reactjs/React-Rails/wiki
84
- The Wiki page features a significant amount of additional information about React-Rails which includes instructional articles and answers to the most frequently asked questions.
85
-
86
-
87
- ## Get started with Shakapacker
88
-
89
- _Alternatively, get started with [Sprockets](#use-with-asset-pipeline)_
90
-
91
- 1. Create a new Rails app:
92
- Prevent installing default javascript dependencies by using `--skip-javascript` option:
93
-
94
- ```bash
95
- rails new my-app --skip-javascript
96
- cd my-app
97
- ```
98
-
99
- 2. Install `shakapacker`:
100
- ```bash
101
- bundle add shakapacker --strict
102
- rails shakapacker:install
103
- ```
104
-
105
- 3. Install `react` and some other required npm packages:
106
- ```bash
107
- yarn add react react-dom @babel/preset-react prop-types \
108
- css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin
109
- ```
110
-
111
- Also update the Babel configuration in the `package.json` file:
112
-
113
- ```diff
114
- "babel": {
115
- "presets": [
116
- - "./node_modules/shakapacker/package/babel/preset.js"
117
- + "./node_modules/shakapacker/package/babel/preset.js",
118
- + "@babel/preset-react"
119
- ]
120
- },
121
- ```
122
-
123
- 4. Install `react-rails`:
124
- ```bash
125
- $ bundle add 'react-rails' --strict
126
- $ rails generate react:install
127
- ```
128
-
129
- This gives you:
130
-
131
- - `app/javascript/components/` directory for your React components
132
- - [`ReactRailsUJS`](#ujs) setup in `app/javascript/packs/application.js`
133
- - `app/javascript/packs/server_rendering.js` for [server-side rendering](#server-side-rendering)
134
-
135
- 5. Generate your first component:
136
- ```bash
137
- $ rails g react:component HelloWorld greeting:string
138
- ```
139
-
140
- You can also generate your component in a subdirectory:
141
-
142
- ```bash
143
- $ rails g react:component my_subdirectory/HelloWorld greeting:string
144
- ```
145
-
146
- Note: Your component is added to `app/javascript/components/` by default.
147
-
148
- Note: If your component is in a subdirectory you will append the directory path to your erb component call.
149
-
150
- Example:
151
- ```erb
152
- <%= react_component("my_subdirectory/HelloWorld", { greeting: "Hello from react-rails." }) %>
153
- ```
154
-
155
- 6. [Render it in a Rails view](#view-helper):
156
-
157
- ```erb
158
- <!-- erb: paste this in view -->
159
- <%= react_component("HelloWorld", { greeting: "Hello from react-rails." }) %>
160
- ```
161
-
162
- 7. Lets Start the app:
163
- ```bash
164
- $ rails s
165
- ```
166
- Output: greeting: Hello from react-rails", inspect webpage in your browser to see the change in tag props.
167
-
168
- 8. Run dev server (optional)
169
- In order to run dev server with HMR feature you need to parallely run:
170
-
171
- ```bash
172
- $ ./bin/shakapacker-dev-server
173
- ```
174
-
175
- Note: On Rails 6 you need to specify `webpack-dev-server` host. To this end, update `config/initializers/content_security_policy.rb` and uncomment relevant lines.
176
-
177
- ### Component name
178
-
179
- The component name tells `react-rails` where to load the component. For example:
180
-
181
- `react_component` call | component `require`
182
- -----|-----
183
- `react_component("Item")` | `require("Item")`
184
- `react_component("items/index")` | `require("items/index")`
185
- `react_component("items.Index")` | `require("items").Index`
186
- `react_component("items.Index.Header")` | `require("items").Index.Header`
187
-
188
- This way, you can access top-level, default, or named exports.
189
-
190
- The `require.context` inserted into `packs/application.js` is used to load components. If you want to load components from a different directory, override it by calling `ReactRailsUJS.useContext`:
191
-
192
- ```js
193
- var myCustomContext = require.context("custom_components", true)
194
- var ReactRailsUJS = require("react_ujs")
195
- // use `custom_components/` for <%= react_component(...) %> calls
196
- ReactRailsUJS.useContext(myCustomContext)
197
- ```
198
-
199
- If `require` fails to find your component, [`ReactRailsUJS`](#ujs) falls back to the global namespace, described in [Use with Asset Pipeline](#use-with-asset-pipeline).
200
-
201
- In some cases, having multiple `require.context` entries may be desired. Examples of this include:
202
-
203
- - Refactoring a typical Rails application into a Rails API with an (eventually) separate Single Page Application (SPA). For this use case, one can add a separate pack in addition to the typical `application` one. React components can be shared between the packs but the new pack can use a minimal Rails view layout, different default styling, etc.
204
- - In a larger application, you might find it helpful to split your JavaScript by routes/controllers to avoid serving unused components and improve your site performance by keeping bundles smaller. For example, you might have separate bundles for homepage, search, and checkout routes. In that scenario, you can add an array of `require.context` component directory paths via `useContexts` to `server_rendering.js`, to allow for [Server-Side Rendering](#server-side-rendering) across your application:
205
-
206
- ```js
207
- // server_rendering.js
208
- var homepageRequireContext = require.context('homepage', true);
209
- var searchRequireContext = require.context('search', true);
210
- var checkoutRequireContext = require.context('checkout', true);
211
-
212
- var ReactRailsUJS = require('react_ujs');
213
- ReactRailsUJS.useContexts([
214
- homepageRequireContext,
215
- searchRequireContext,
216
- checkoutRequireContext
217
- ]);
218
- ```
219
- ### File naming
220
-
221
- React-Rails supports plenty of file extensions such as: .js, .jsx.js, .js.jsx, .es6.js, .coffee, etcetera!
222
- Sometimes this will cause a stumble when searching for filenames.
223
-
224
- Component File Name | `react_component` call
225
- -----|-----
226
- `app/javascript/components/samplecomponent.js` | `react_component("samplecomponent")`
227
- `app/javascript/components/sample_component.js` | `react_component("sample_component")`
228
- `app/javascript/components/SampleComponent.js` | `react_component("SampleComponent")`
229
- `app/javascript/components/SampleComponent.js.jsx` | Has to be renamed to SampleComponent.jsx, then use `react_component("SampleComponent")`
230
-
231
- ### Typescript support
232
-
233
- ```bash
234
- yarn add typescript @babel/preset-typescript
235
- ```
236
-
237
- Babel won’t perform any type-checking on TypeScript code. To optionally use type-checking run:
238
-
239
- ```bash
240
- yarn add fork-ts-checker-webpack-plugin
241
- ```
242
-
243
- Add `tsconfig.json` with the following content:
244
-
245
- ```json
246
- {
247
- "compilerOptions": {
248
- "declaration": false,
249
- "emitDecoratorMetadata": true,
250
- "experimentalDecorators": true,
251
- "lib": ["es6", "dom"],
252
- "module": "es6",
253
- "moduleResolution": "node",
254
- "sourceMap": true,
255
- "target": "es5",
256
- "jsx": "react",
257
- "noEmit": true
258
- },
259
- "exclude": ["**/*.spec.ts", "node_modules", "vendor", "public"],
260
- "compileOnSave": false
261
- }
262
- ```
263
-
264
- Then modify the webpack config to use it as a plugin:
265
-
266
- ```js
267
- // config/webpack/webpack.config.js
268
- const { webpackConfig, merge } = require("shakapacker");
269
- const ForkTSCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
270
-
271
- module.exports = merge(webpackConfig, {
272
- plugins: [new ForkTSCheckerWebpackPlugin()],
273
- });
274
- ```
275
-
276
- Doing this will allow React-Rails to support the .tsx extension. Additionally, it is recommended to add `ts` and `tsx` to the `server_renderer_extensions` in your application configuration:
277
-
278
- ```ruby
279
- config.react.server_renderer_extensions = ["jsx", "js", "tsx", "ts"]
280
- ```
281
-
282
- ### Test component
283
-
284
- You can use `assert_react_component` to test component render:
285
-
286
- ```erb
287
- <!-- app/views/welcome/index.html.erb -->
288
-
289
- <%= react_component("HelloWorld", { greeting: "Hello from react-rails.", info: { name: "react-rails" } }, { class: "hello-world" }) %>
290
- ```
291
-
292
- ```rb
293
- class WelcomeControllerTest < ActionDispatch::IntegrationTest
294
- test 'assert_react_component' do
295
- get "/welcome"
296
- assert_equal 200, response.status
297
-
298
- # assert rendered react component and check the props
299
- assert_react_component "HelloWorld" do |props|
300
- assert_equal "Hello from react-rails.", props[:greeting]
301
- assert_equal "react-rails", props[:info][:name]
302
- assert_select "[class=?]", "hello-world"
303
- end
304
-
305
- # or just assert component rendered
306
- assert_react_component "HelloWorld"
307
- end
308
- end
309
- ```
310
-
311
- ## Use with Asset Pipeline
312
-
313
- `react-rails` provides a pre-bundled React.js & a UJS driver to the Rails asset pipeline. Get started by adding the `react-rails` gem:
314
-
315
- ```ruby
316
- gem 'react-rails'
317
- ```
318
-
319
- And then install the react generator:
320
-
321
- ```
322
- $ rails g react:install
323
- ```
324
-
325
- Then restart your development server.
326
-
327
- This will:
328
-
329
- - add some `//= require`s to `application.js`
330
- - add a `components/` directory for React components
331
- - add `server_rendering.js` for [server-side rendering](#server-side-rendering)
332
-
333
- Now, you can create React components in `.jsx` files:
334
-
335
- ```JSX
336
- // app/assets/javascripts/components/post.jsx
337
-
338
- window.Post = createReactClass({
339
- render: function() {
340
- return <h1>{this.props.title}</h1>
341
- }
342
- })
343
-
344
- // or, equivalent:
345
- class Post extends React.Component {
346
- render() {
347
- return <h1>{this.props.title}</h1>
348
- }
349
- }
350
- ```
351
-
352
- Then, you can render those [components in views](#view-helper):
353
-
354
- ```erb
355
- <%= react_component("Post", {title: "Hello World"}) %>
356
- ```
357
-
358
- Components must be accessible from the top level, but they may be namespaced, for example:
359
-
360
- ```erb
361
- <%= react_component("Comments.NewForm", {post_id: @post.id}) %>
362
- <!-- looks for `window.Comments.NewForm` -->
363
- ```
364
-
365
- ### Custom JSX Transformer
366
-
367
- `react-rails` uses a transformer class to transform JSX in the asset pipeline. The transformer is initialized once, at boot. You can provide a custom transformer to `config.react.jsx_transformer_class`. The transformer must implement:
368
-
369
- - `#initialize(options)`, where options is the value passed to `config.react.jsx_transform_options`
370
- - `#transform(code_string)` to return a string of transformed code
371
-
372
- `react-rails` provides two transformers, `React::JSX::BabelTransformer` (which uses [ruby-babel-transpiler](https://github.com/babel/ruby-babel-transpiler)) and `React::JSX::JSXTransformer` (which uses the deprecated `JSXTransformer.js`).
373
-
374
- #### Transform Plugin Options
375
-
376
- To supply additional transform plugins to your JSX Transformer, assign them to `config.react.jsx_transform_options`
377
-
378
- `react-rails` uses the Babel version of the `babel-source` gem.
379
-
380
- For example, to use `babel-plugin-transform-class-properties` :
381
-
382
- config.react.jsx_transform_options = {
383
- optional: ['es7.classProperties']
384
- }
385
-
386
- ### React.js versions
387
-
388
- `//= require react` brings `React` into your project.
389
-
390
- By default, React's [development version] is provided to `Rails.env.development`. You can override the React build with a config:
391
-
392
- ```ruby
393
- # Here are the defaults:
394
- # config/environments/development.rb
395
- MyApp::Application.configure do
396
- config.react.variant = :development
397
- end
398
-
399
- # config/environments/production.rb
400
- MyApp::Application.configure do
401
- config.react.variant = :production
402
- end
403
- ```
404
-
405
- Be sure to restart your Rails server after changing these files. See [VERSIONS.md](https://github.com/reactjs/react-rails/blob/master/VERSIONS.md) to learn which version of React.js is included with your `react-rails` version. In some edge cases you may need to bust the sprockets cache with `rake tmp:clear`
406
-
407
-
408
- ## View Helper
409
-
410
- `react-rails` includes a view helper and an [unobtrusive JavaScript driver](#ujs) which work together to put React components on the page.
411
-
412
- The view helper (`react_component`) puts a `div` on the page with the requested component class & props. For example:
413
-
414
- ```erb
415
- <%= react_component('HelloMessage', name: 'John') %>
416
- <!-- becomes: -->
417
- <div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}"></div>
418
- ```
419
-
420
- On page load, the [`react_ujs` driver](#ujs) will scan the page and mount components using `data-react-class`
421
- and `data-react-props`.
422
-
423
- The view helper's signature is:
424
-
425
- ```ruby
426
- react_component(component_class_name, props={}, html_options={})
427
- ```
428
-
429
- - `component_class_name` is a string which identifies a component. See [getConstructor](#getconstructor) for details.
430
- - `props` is either:
431
- - an object that responds to `#to_json`; or
432
- - an already-stringified JSON object (see [JBuilder note](#use-with-jbuilder) below).
433
- - `html_options` may include:
434
- - `tag:` to use an element other than a `div` to embed `data-react-class` and `data-react-props`.
435
- - `prerender: true` to render the component on the server.
436
- - `camelize_props` to [transform a props hash](#camelize-props)
437
- - `**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).
438
-
439
-
440
- #### Custom View Helper
441
-
442
- `react-rails` uses a "helper implementation" class to generate the output of the `react_component` helper. The helper is initialized once per request and used for each `react_component` call during that request. You can provide a custom helper class to `config.react.view_helper_implementation`. The class must implement:
443
-
444
- - `#react_component(name, props = {}, options = {}, &block)` to return a string to inject into the Rails view
445
- - `#setup(controller_instance)`, called when the helper is initialized at the start of the request
446
- - `#teardown(controller_instance)`, called at the end of the request
447
-
448
- `react-rails` provides one implementation, `React::Rails::ComponentMount`.
449
-
450
- ## UJS
451
-
452
- `react-rails`'s JavaScript is available as `"react_ujs"` in the asset pipeline or from NPM. It attaches itself to the window as `ReactRailsUJS`.
453
-
454
- ### Mounting & Unmounting
455
-
456
- Usually, `react-rails` mounts & unmounts components automatically as described in [Event Handling](#event-handling) below.
457
-
458
- You can also mount & unmount components from `<%= react_component(...) %>` tags using UJS:
459
-
460
- ```js
461
- // Mount all components on the page:
462
- ReactRailsUJS.mountComponents()
463
- // Mount components within a selector:
464
- ReactRailsUJS.mountComponents(".my-class")
465
- // Mount components within a specific node:
466
- ReactRailsUJS.mountComponents(specificDOMnode)
467
-
468
- // Unmounting works the same way:
469
- ReactRailsUJS.unmountComponents()
470
- ReactRailsUJS.unmountComponents(".my-class")
471
- ReactRailsUJS.unmountComponents(specificDOMnode)
472
- ```
473
-
474
- You can use this when the DOM is modified by AJAX calls or modal windows.
475
-
476
- ### Event Handling
477
-
478
- `ReactRailsUJS` checks for various libraries to support their page change events:
479
-
480
- - `Turbolinks`
481
- - `pjax`
482
- - `jQuery`
483
- - Native DOM events
484
-
485
- `ReactRailsUJS` will automatically mount components on `<%= react_component(...) %>` tags and unmount them when appropriate.
486
-
487
- If you need to re-detect events, you can call `detectEvents`:
488
-
489
- ```js
490
- // Remove previous event handlers and add new ones:
491
- ReactRailsUJS.detectEvents()
492
- ```
493
-
494
- For example, if `Turbolinks` is loaded _after_ `ReactRailsUJS`, you'll need to call this again. This function removes previous handlers before adding new ones, so it's safe to call as often as needed.
495
-
496
- If `Turbolinks` is `import`ed via Shakapacker (and thus not available globally), `ReactRailsUJS` will be unable to locate it. To fix this, you can temporarily add it to the global namespace:
497
-
498
- ```js
499
- // Order is particular. First start Turbolinks:
500
- Turbolinks.start();
501
- // Add Turbolinks to the global namespace:
502
- window.Turbolinks = Turbolinks;
503
- // Remove previous event handlers and add new ones:
504
- ReactRailsUJS.detectEvents();
505
- // (Optional) Clean up global namespace:
506
- delete window.Turbolinks;
507
- ```
508
-
509
- ### `getConstructor`
510
-
511
- Components are loaded with `ReactRailsUJS.getConstructor(className)`. This function has two default implementations, depending on if you're using the asset pipeline or Shakapacker:
512
-
513
- - On the asset pipeline, it looks up `className` in the global namespace (`ReactUJS.constructorFromGlobal`).
514
- - On Shakapacker, it `require`s files and accesses named exports, as described in [Get started with Shakapacker](#get-started-with-shakapacker), falling back to the global namespace (`ReactUJS.constructorFromRequireContextWithGlobalFallback`).
515
-
516
- You can override this function to customize the mapping of name-to-constructor. [Server-side rendering](#server-side-rendering) also uses this function.
517
-
518
- For example, the fallback behavior of
519
- `ReactUJS.constructorFromRequireContextWithGlobalFallback` can sometimes make
520
- server-side rendering errors hard to debug as it will swallow the original error
521
- (more info
522
- [here](https://github.com/reactjs/react-rails/issues/264#issuecomment-552326663)).
523
- `ReactUJS.constructorFromRequireContext` is provided for this reason. You can
524
- use it like so:
525
-
526
- ```js
527
- // Replaces calls to `ReactUJS.useContext`
528
- ReactUJS.getConstructor = ReactUJS.constructorFromRequireContext(require.context('components', true));
529
- ```
530
-
531
-
532
- ## Server-Side Rendering
533
-
534
- You can render React components inside your Rails server with `prerender: true`:
535
-
536
- ```erb
537
- <%= react_component('HelloMessage', {name: 'John'}, {prerender: true}) %>
538
- <!-- becomes: -->
539
- <div data-react-class="HelloMessage" data-react-props="{&quot;name&quot;:&quot;John&quot;}">
540
- <h1>Hello, John!</h1>
541
- </div>
542
- ```
543
-
544
- _(It will also be mounted by the [UJS](#ujs) on page load.)_
545
-
546
- Server rendering is powered by [`ExecJS`](https://github.com/rails/execjs) and subject to some requirements:
547
-
548
- - `react-rails` must load your code. By convention, it uses `server_rendering.js`, which was created
549
- by the install task. This file must include your components _and_ their dependencies (eg, Underscore.js).
550
- - Requires separate compilations for server & client bundles (see [Webpack config](https://github.com/reactjs/react-rails/tree/master/test/dummy/config/webpack))
551
- - Your code can't reference `document` or `window`. Prerender processes don't have access to `document` or `window`,
552
- so jQuery and some other libs won't work in this environment :(
553
-
554
- `ExecJS` supports many backends. CRuby users will get the best performance from [`mini_racer`](https://github.com/discourse/mini_racer#performance).
555
-
556
- #### Configuration
557
-
558
- Server renderers are stored in a pool and reused between requests. Threaded Rubies (eg jRuby) may see a benefit to increasing the pool size beyond the default `0`.
559
-
560
- These are the default configurations:
561
-
562
- ```ruby
563
- # config/application.rb
564
- # These are the defaults if you don't specify any yourself
565
- module MyApp
566
- class Application < Rails::Application
567
- # Settings for the pool of renderers:
568
- config.react.server_renderer_pool_size ||= 1 # ExecJS doesn't allow more than one on MRI
569
- config.react.server_renderer_timeout ||= 20 # seconds
570
- config.react.server_renderer = React::ServerRendering::BundleRenderer
571
- config.react.server_renderer_options = {
572
- files: ["server_rendering.js"], # files to load for prerendering
573
- replay_console: true, # if true, console.* will be replayed client-side
574
- }
575
- # Changing files matching these dirs/exts will cause the server renderer to reload:
576
- config.react.server_renderer_extensions = ["jsx", "js"]
577
- config.react.server_renderer_directories = ["/app/assets/javascripts", "/app/javascript/"]
578
- end
579
- end
580
- ```
581
-
582
- #### JavaScript State
583
-
584
- Some of ExecJS's backends are stateful (eg, mini_racer, therubyracer). This means that any side-effects of a prerender will affect later renders with that renderer.
585
-
586
- To manage state, you have a couple options:
587
-
588
- - Make a custom renderer with `#before_render` / `#after_render` hooks as [described below](#custom-server-renderer)
589
- - Use `per_request_react_rails_prerenderer` to manage state for a whole controller action.
590
-
591
- To check out a renderer for the duration of a controller action, call the `per_request_react_rails_prerenderer` helper in the controller class:
592
-
593
- ```ruby
594
- class PagesController < ApplicationController
595
- # Use the same React server renderer for the entire request:
596
- per_request_react_rails_prerenderer
597
- end
598
- ```
599
-
600
- Then, you can access the ExecJS context directly with `react_rails_prerenderer.context`:
601
-
602
- ```ruby
603
- def show
604
- react_rails_prerenderer # => #<React::ServerRendering::BundleRenderer>
605
- react_rails_prerenderer.context # => #<ExecJS::Context>
606
-
607
- # Execute arbitrary JavaScript code
608
- # `self` is the global context
609
- react_rails_prerenderer.context.exec("self.Store.setup()")
610
- render :show
611
- react_rails_prerenderer.context.exec("self.Store.teardown()")
612
- end
613
- ```
614
-
615
- `react_rails_prerenderer` may also be accessed in before- or after-actions.
616
-
617
- #### Custom Server Renderer
618
-
619
- `react-rails` depends on a renderer class for rendering components on the server. You can provide a custom renderer class to `config.react.server_renderer`. The class must implement:
620
-
621
- - `#initialize(options={})`, which accepts the hash from `config.react.server_renderer_options`
622
- - `#render(component_name, props, prerender_options)` to return a string of HTML
623
-
624
- `react-rails` provides two renderer classes: `React::ServerRendering::ExecJSRenderer` and `React::ServerRendering::BundleRenderer`.
625
-
626
- `ExecJSRenderer` offers two other points for extension:
627
-
628
- - `#before_render(component_name, props, prerender_options)` to return a string of JavaScript to execute _before_ calling `React.render`
629
- - `#after_render(component_name, props, prerender_options)` to return a string of JavaScript to execute _after_ calling `React.render`
630
-
631
- Any subclass of `ExecJSRenderer` may use those hooks (for example, `BundleRenderer` uses them to handle `console.*` on the server).
632
-
633
- ## Controller Actions
634
-
635
- Components can also be server-rendered directly from a controller action with the custom `component` renderer. For example:
636
-
637
- ```ruby
638
- class TodoController < ApplicationController
639
- def index
640
- @todos = Todo.all
641
- render component: 'TodoList', props: { todos: @todos }, tag: 'span', class: 'todo'
642
- end
643
- end
644
- ```
645
-
646
- You can also provide the "usual" `render` arguments: `content_type`, `layout`, `location` and `status`. By default, your current layout will be used and the component, rather than a view, will be rendered in place of `yield`. Custom data-* attributes can be passed like `data: {remote: true}`.
647
-
648
- Prerendering is set to `true` by default, but can be turned off with `prerender: false`.
649
-
650
- ## Component Generator
651
-
652
- You can generate a new component file with:
653
-
654
- ```sh
655
- rails g react:component ComponentName prop1:type prop2:type ... [options]
656
- ```
657
-
658
- For example,
659
-
660
- ```sh
661
- rails g react:component Post title:string published:bool published_by:instanceOf{Person}
662
- ```
663
-
664
- would generate:
665
-
666
- ```JSX
667
- var Post = createReactClass({
668
- propTypes: {
669
- title: PropTypes.string,
670
- published: PropTypes.bool,
671
- publishedBy: PropTypes.instanceOf(Person)
672
- },
673
-
674
- render: function() {
675
- return (
676
- <React.Fragment>
677
- Title: {this.props.title}
678
- Published: {this.props.published}
679
- Published By: {this.props.publishedBy}
680
- </React.Fragment>
681
- );
682
- }
683
- });
684
- ```
685
-
686
- The generator also accepts options:
687
-
688
- - `--es6`: generates a function component
689
- - `--coffee`: use CoffeeScript
690
-
691
- For example,
692
-
693
- ```sh
694
- rails g react:component ButtonComponent title:string --es6
695
- ```
696
-
697
- would generate:
698
-
699
- ```jsx
700
- import React from "react"
701
- import PropTypes from "prop-types"
702
-
703
- function ButtonComponent(props) {
704
- return (
705
- <React.Fragment>
706
- Title: {this.props.title}
707
- </React.Fragment>
708
- );
709
- }
710
-
711
- ButtonComponent.propTypes = {
712
- title: PropTypes.string
713
- };
714
-
715
- export default ButtonComponent
716
- ```
717
-
718
- **Note:** In a Shakapacker project, es6 template is the default template in the generator.
719
-
720
- Accepted PropTypes are:
721
-
722
- - Plain types: `any`, `array`, `bool`, `element`, `func`, `number`, `object`, `node`, `shape`, `string`
723
- - `instanceOf` takes an optional class name in the form of `instanceOf{className}`.
724
- - `oneOf` behaves like an enum, and takes an optional list of strings in the form of `'name:oneOf{one,two,three}'`.
725
- - `oneOfType` takes an optional list of react and custom types in the form of `'model:oneOfType{string,number,OtherType}'`.
726
-
727
- Note that the arguments for `oneOf` and `oneOfType` must be enclosed in single quotes
728
- to prevent your terminal from expanding them into an argument list.
729
-
730
- #### Use with JBuilder
731
-
732
- If you use Jbuilder to pass a JSON string to `react_component`, make sure your JSON is a stringified hash,
733
- not an array. This is not the Rails default -- you should add the root node yourself. For example:
734
-
735
- ```ruby
736
- # BAD: returns a stringified array
737
- json.array!(@messages) do |message|
738
- json.extract! message, :id, :name
739
- json.url message_url(message, format: :json)
740
- end
741
-
742
- # GOOD: returns a stringified hash
743
- json.messages(@messages) do |message|
744
- json.extract! message, :id, :name
745
- json.url message_url(message, format: :json)
746
- end
747
- ```
748
-
749
- ### Camelize Props
750
-
751
- You can configure `camelize_props` option:
752
-
753
- ```ruby
754
- MyApp::Application.configure do
755
- config.react.camelize_props = true # default false
756
- end
757
- ```
758
-
759
- Now, Ruby hashes given to `react_component(...)` as props will have their keys transformed from _underscore_- to _camel_-case, for example:
760
-
761
- ```ruby
762
- { all_todos: @todos, current_status: @status }
763
- # becomes:
764
- { "allTodos" => @todos, "currentStatus" => @status }
765
- ```
766
-
767
- You can also specify this option in `react_component`:
768
-
769
- ```erb
770
- <%= react_component('HelloMessage', {name: 'John'}, {camelize_props: true}) %>
771
- ```
772
-
773
- ### Changing Component Templates
774
-
775
- To make simple changes to Component templates, copy the respective template file to your Rails project at `lib/templates/react/component/template_filename`.
776
-
777
- For example, to change the [ES6 Component template](https://github.com/reactjs/react-rails/blob/master/lib/generators/templates/component.es6.jsx), copy it to `lib/templates/react/component/component.es6.jsx` and modify it.
778
-
779
- ## Upgrading
780
-
781
- ### 2.7 to 3.0
782
- - Keep your `react_ujs` up to date: `yarn upgrade`
783
- - **Drop support for Webpacker:** Before any ReactRails upgrade, make sure upgrading from Webpacker to Shakapacker 7. For more information check out Shakapacker
784
- - **SSR:** ReactRails 3.x requires separate compilations for server & client bundles. See [Webpack config](https://github.com/reactjs/react-rails/tree/master/test/dummy/config/webpack) directory in the dummy app to addapt the new implementation.
785
-
786
- ### 2.3 to 2.4
787
-
788
- Keep your `react_ujs` up to date, `yarn upgrade`
789
-
790
- React-Rails 2.4.x uses React 16+ which no longer has React Addons. Therefore the pre-bundled version of react no longer has an addons version, if you need addons still, there is the 2.3.1+ version of the gem that still has addons.
791
-
792
- If you need to make changes in your components for the prebundled react, see the migration docs here:
793
-
794
- - https://reactjs.org/blog/2016/11/16/react-v15.4.0.html
795
- - https://reactjs.org/blog/2017/04/07/react-v15.5.0.html
796
- - https://reactjs.org/blog/2017/06/13/react-v15.6.0.html
797
-
798
-
799
- For the vast majority of cases this will get you most of the migration:
800
- - global find+replace `React.Prop` -> `Prop`
801
- - add `import PropTypes from 'prop-types'` (Webpacker only)
802
- - re-run `bundle exec rails webpacker:install:react` to update npm packages (Webpacker only)
803
-
804
- ## Common Errors
805
- ### Getting warning for `Can't resolve 'react-dom/client'` in React < 18
806
-
807
- You may see a warning like this when building a Webpack bundle using any version of React below 18. This warning can be safely [suppressed](https://webpack.js.org/configuration/other-options/#ignorewarnings) in your Webpack configuration. The following is an example of this suppression in `config/webpack/webpack.config.js`:
808
-
809
- ```diff
810
- - const { webpackConfig } = require('shakapacker')
811
- + const { webpackConfig, merge } = require('shakapacker')
812
-
813
- +const ignoreWarningsConfig = {
814
- + ignoreWarnings: [/Module not found: Error: Can't resolve 'react-dom\/client'/],
815
- +};
816
-
817
- - module.exports = webpackConfig
818
- + module.exports = merge({}, webpackConfig, ignoreWarningsConfig)
819
- ```
820
-
821
- ### Undefined Set
822
- ```
823
- ExecJS::ProgramError (identifier 'Set' undefined):
824
-
825
- (execjs):1
826
- ```
827
- If you see any variation of this issue, see [Using TheRubyRacer](#using-therubyracer)
828
-
829
-
830
- ### Using TheRubyRacer
831
- TheRubyRacer [hasn't updated LibV8](https://github.com/cowboyd/therubyracer/blob/master/therubyracer.gemspec#L20) (The library that powers Node.js) from v3 in 2 years, any new features are unlikely to work.
832
-
833
- LibV8 itself is already [beyond version 7](https://github.com/cowboyd/libv8/releases/tag/v7.3.492.27.1) therefore many serverside issues are caused by old JS engines and fixed by using an up to date one such as [MiniRacer](https://github.com/discourse/mini_racer) or [TheRubyRhino](https://github.com/cowboyd/therubyrhino) on JRuby.
834
-
835
- ### HMR
836
-
837
- Check out [Enabling Hot Module Replacement (HMR)](https://github.com/shakacode/shakapacker/blob/master/docs/react.md#enabling-hot-module-replacement-hmr) in Shakapacker documentation.
838
-
839
- One caveat is that currently you [cannot Server-Side Render along with HMR](https://github.com/reactjs/react-rails/issues/925#issuecomment-415469572).
93
+ The Wiki page features a significant amount of additional information about React-Rails, including instructional articles and answers to the most frequently asked questions.
840
94
 
841
95
  ## Related Projects
842
96
 
843
- - [webpacker-react](https://github.com/renchap/webpacker-react): Integration of React with Rails utilizing Webpack with Hot Module Replacement (HMR).
844
- - [The React on Rails Course](https://learnetto.com/users/hrishio/courses/the-free-react-on-rails-5-course) A video course which teaches the basics of React and how to get started using it in Rails with `react-rails`.
845
97
  - [react\_on\_rails](https://github.com/shakacode/react_on_rails): Integration of React with Rails utilizing Webpack, Redux, React-Router.
846
- - [react-rails-hot-loader](https://github.com/rmosolgo/react-rails-hot-loader) Simple live-reloader for `react-rails`.
98
+ - [React on Rails Pro](https://www.shakacode.com/react-on-rails-pro/):React on Rails with Node rendering and many other performance enhancements.
847
99
  - [react-rails-benchmark_renderer](https://github.com/pboling/react-rails-benchmark_renderer) adds performance instrumentation to server rendering.
848
100
  - [Ruby Hyperstack](https://hyperstack.org/): Use Ruby to build reactive user interfaces with React.
849
101
 
850
102
  ## Contributing
851
103
 
852
- 🎉 Thanks for taking the time to contribute! 🎉
853
-
854
- With 5 Million+ downloads of the react-rails Gem and another 2 Million+ downloads of react_ujs on NPM, you're helping the biggest React + Rails community!
855
-
856
- By contributing to React-Rails, you agree to abide by the [code of conduct](https://github.com/reactjs/react-rails/blob/master/CODE_OF_CONDUCT.md).
857
-
858
- You can always help by submitting patches or triaging issues. Even offering reproduction steps to issues is incredibly helpful!
104
+ 🎉 Thanks for taking the time to contribute! 🎉 See [CONTRIBUTING.md](./CONTRIBUTING.md) for more details.
859
105
 
860
106
  # Supporters
861
107
 
862
- The following companies support the development of this and other open-source projects maintained by ShakaCode by providing licenses to the ShakaCode team. ShakaCode stands by the usefulness of these products!
108
+ The following companies provide licenses to the ShakaCode team, supporting the development of this and other open-source projects maintained by ShakaCode. ShakaCode stands by the usefulness of these products!
863
109
 
864
110
  <br />
865
111
  <br />
@@ -888,4 +134,6 @@ The following companies support the development of this and other open-source pr
888
134
  </picture>
889
135
  </a>
890
136
 
891
- Please see our [Contribution guide](https://github.com/reactjs/react-rails/blob/master/CONTRIBUTING.md) for more info.
137
+ ---
138
+
139
+ ShakaCode is [hiring](https://jobs.lever.co/shakacode/3bdbfdb3-4495-4611-a279-01dddddb351abe)!
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("react-dom"),require("react-dom/server")):"function"==typeof define&&define.amd?define(["react","react-dom","react-dom/server"],t):"object"==typeof exports?exports.ReactRailsUJS=t(require("react"),require("react-dom"),require("react-dom/server")):e.ReactRailsUJS=t(e.React,e.ReactDOM,e.ReactDOMServer)}(self,((__WEBPACK_EXTERNAL_MODULE__787__,__WEBPACK_EXTERNAL_MODULE__156__,__WEBPACK_EXTERNAL_MODULE__997__)=>(()=>{var __webpack_modules__={634:(e,t,n)=>{"use strict";var o=n(156);t.createRoot=o.createRoot,t.hydrateRoot=o.hydrateRoot},10:(e,t,n)=>{var o=n(787),r=n(156),a=n(997),u=n(230),c=n(121),d=n(831),i=n(37),s=n(39),{supportsHydration:_,reactHydrate:l,createReactRootLike:p}=n(198),f=n(613),v={CLASS_NAME_ATTR:"data-react-class",PROPS_ATTR:"data-react-props",RENDER_ATTR:"data-hydrate",CACHE_ID_ATTR:"data-react-cache-id",TURBOLINKS_PERMANENT_ATTR:"data-turbolinks-permanent",jQuery:"undefined"!=typeof window&&void 0!==window.jQuery&&window.jQuery,components:{},roots:[],findDOMNodes:function(e){var t,n,o=v.CLASS_NAME_ATTR;switch(typeof e){case"undefined":t="["+o+"]",n=document;break;case"object":t="["+o+"]",n=e;break;case"string":t=e+"["+o+"], "+e+" ["+o+"]",n=document}return v.jQuery?v.jQuery(t,n):n.querySelectorAll(t)},getConstructor:c,constructorFromGlobal:c,constructorFromRequireContext:d,constructorFromRequireContextWithGlobalFallback:i,useContext:function(e){this.getConstructor=i(e)},useContexts:function(e){this.getConstructor=s(e)},serverRender:function(e,t,n){var r=this.getConstructor(t),u=o.createElement(r,n);return a[e](u)},mountComponents:function(e){for(var t=v,n=t.findDOMNodes(e),r=0;r<n.length;++r){var a=n[r],u=a.getAttribute(t.CLASS_NAME_ATTR),c=t.getConstructor(u),d=a.getAttribute(t.PROPS_ATTR),i=d&&JSON.parse(d),s=a.getAttribute(t.RENDER_ATTR),E=a.getAttribute(t.CACHE_ID_ATTR),h=a.hasAttribute(t.TURBOLINKS_PERMANENT_ATTR);if(!c){var m="Cannot find component: '"+u+"'";throw console&&console.log&&console.log("%c[react-rails] %c"+m+" for element","font-weight: bold","",a),new Error(m+". Make sure your component is available to render.")}var b=this.components[E];if(void 0===b&&(b=o.createElement(c,i),h&&(this.components[E]=b)),s&&_())b=l(a,b);else{const e=p(a);b=e.render(b),f&&this.roots.push({node:a,root:e})}}},unmountComponents:function(e){for(var t=v.findDOMNodes(e),n=0;n<t.length;++n){var o=t[n];f?this.unmountRoot(o):r.unmountComponentAtNode(o)}},detectEvents:function(){u(this)},unmountRoot:function(e){this.roots.filter((function(t){return t.node&&t.node===e})).forEach((function(e){e.root.unmount(),e.root=null,e.node=null}))},handleMount:function(e){var t=void 0;e&&e.target&&(t=e.target),v.mountComponents(t)},handleUnmount:function(e){e&&e.target&&e.target}};"undefined"!=typeof window&&v.detectEvents(),self.ReactRailsUJS=v,e.exports=v},230:(e,t,n)=>{var o=n(528),r=n(921),a=n(228),u=n(724),c=n(968);e.exports=function(e){e.handleEvent&&("undefined"!=typeof Turbolinks&&void 0!==Turbolinks.EVENTS&&c.teardown(e),a.teardown(e),u.teardown(e),r.teardown(e),o.teardown(e)),"addEventListener"in window?(e.handleEvent=function(e,t){document.addEventListener(e,t)},e.removeEvent=function(e,t){document.removeEventListener(e,t)}):(e.handleEvent=function(e,t){window.attachEvent(e,t)},e.removeEvent=function(e,t){window.detachEvent(e,t)}),"undefined"!=typeof Turbolinks&&Turbolinks.supported?void 0!==Turbolinks.EVENTS?c.setup(e):void 0!==Turbolinks.controller?a.setup(e):u.setup(e):"undefined"!=typeof $&&"function"==typeof $.pjax?r.setup(e):o.setup(e)}},528:e=>{e.exports={setup:function(e){"addEventListener"in window?e.handleEvent("DOMContentLoaded",e.handleMount):e.handleEvent("onload",e.handleMount)},teardown:function(e){e.removeEvent("DOMContentLoaded",e.handleMount),e.removeEvent("onload",e.handleMount)}}},921:e=>{e.exports={setup:function(e){e.handleEvent("ready",e.handleMount),e.handleEvent("pjax:end",e.handleMount),e.handleEvent("pjax:beforeReplace",e.handleUnmount)},teardown:function(e){e.removeEvent("ready",e.handleMount),e.removeEvent("pjax:end",e.handleMount),e.removeEvent("pjax:beforeReplace",e.handleUnmount)}}},228:e=>{e.exports={setup:function(e){e.handleEvent("turbolinks:load",e.handleMount)},teardown:function(e){e.removeEvent("turbolinks:load",e.handleMount)}}},968:e=>{e.exports={setup:function(e){e.handleEvent(Turbolinks.EVENTS.CHANGE,e.handleMount),e.handleEvent(Turbolinks.EVENTS.BEFORE_UNLOAD,e.handleUnmount)},teardown:function(e){e.removeEvent(Turbolinks.EVENTS.CHANGE,e.handleMount),e.removeEvent(Turbolinks.EVENTS.BEFORE_UNLOAD,e.handleUnmount)}}},724:e=>{e.exports={setup:function(e){Turbolinks.pagesCached(0),e.handleEvent("page:change",e.handleMount),e.handleEvent("page:receive",e.handleUnmount)},teardown:function(e){e.removeEvent("page:change",e.handleMount),e.removeEvent("page:receive",e.handleUnmount)}}},121:function(module){var topLevel="undefined"==typeof window?this:window;module.exports=function(className){var constructor;return constructor=topLevel[className],constructor||(constructor=eval(className)),constructor&&constructor.default&&(constructor=constructor.default),constructor}},831:e=>{e.exports=function(e){return function(t){var n=t.split("."),o=n.shift(),r=n,a=e("./"+o);return r.forEach((function(e){a=a[e]})),a.__esModule&&(a=a.default),a}}},37:(e,t,n)=>{var o=n(121),r=n(831);e.exports=function(e){var t=r(e);return function(e){var n;try{n=t(e)}catch(t){try{n=o(e)}catch(e){console.error(t),console.error(e)}}return n}}},39:(e,t,n)=>{var o=n(121),r=n(831);e.exports=function(e){var t=e.map((e=>r(e)));return function(e){var n;try{var r,a,u=0;do{r=t[u];try{n=r(e)}catch(e){a||(a=e)}u+=1}while(u<t.length);if(!n)throw a}catch(a){try{n=o(e)}catch(e){console.error(a),console.error(e)}}return n}}},198:(e,t,n)=>{"use strict";n.r(t),n.d(t,{createReactRootLike:()=>_,reactHydrate:()=>s,supportsHydration:()=>i});var o=n(156),r=n.n(o),a=n(613),u=n.n(a);let c=r();if(u())try{c=n(634)}catch(e){c=r()}const d=c;function i(){return"function"==typeof d.hydrate||"function"==typeof d.hydrateRoot}function s(e,t){return"function"==typeof d.hydrateRoot?d.hydrateRoot(e,t):d.hydrate(t,e)}function _(e){return u()?d.createRoot(e):function(e){return{render:t=>d.render(t,e)}}(e)}},613:(e,t,n)=>{var o,r=n(156);o=void 0!==r&&(r.version.split(".")[0]||16)>=18,e.exports=o},787:e=>{"use strict";e.exports=__WEBPACK_EXTERNAL_MODULE__787__},156:e=>{"use strict";e.exports=__WEBPACK_EXTERNAL_MODULE__156__},997:e=>{"use strict";e.exports=__WEBPACK_EXTERNAL_MODULE__997__}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__(10);return __webpack_exports__})()));
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("react-dom"),require("react-dom/server")):"function"==typeof define&&define.amd?define(["react","react-dom","react-dom/server"],t):"object"==typeof exports?exports.ReactRailsUJS=t(require("react"),require("react-dom"),require("react-dom/server")):e.ReactRailsUJS=t(e.React,e.ReactDOM,e.ReactDOMServer)}(self,((__WEBPACK_EXTERNAL_MODULE__787__,__WEBPACK_EXTERNAL_MODULE__156__,__WEBPACK_EXTERNAL_MODULE__997__)=>(()=>{var __webpack_modules__={634:(e,t,n)=>{"use strict";var o=n(156);t.createRoot=o.createRoot,t.hydrateRoot=o.hydrateRoot},10:(e,t,n)=>{var o=n(787),r=n(156),a=n(997),u=n(230),c=n(121),i=n(831),d=n(37),s=n(39),{supportsHydration:_,reactHydrate:l,createReactRootLike:p}=n(198),f=n(613),v={CLASS_NAME_ATTR:"data-react-class",PROPS_ATTR:"data-react-props",RENDER_ATTR:"data-hydrate",CACHE_ID_ATTR:"data-react-cache-id",TURBOLINKS_PERMANENT_ATTR:"data-turbolinks-permanent",jQuery:"undefined"!=typeof window&&void 0!==window.jQuery&&window.jQuery,components:{},roots:[],findDOMNodes:function(e){var t,n,o=v.CLASS_NAME_ATTR;switch(typeof e){case"undefined":t="["+o+"]",n=document;break;case"object":t="["+o+"]",n=e;break;case"string":t=e+"["+o+"], "+e+" ["+o+"]",n=document}return v.jQuery?v.jQuery(t,n):n.querySelectorAll(t)},getConstructor:c,constructorFromGlobal:c,constructorFromRequireContext:i,constructorFromRequireContextWithGlobalFallback:d,useContext:function(e){this.getConstructor=d(e)},useContexts:function(e){this.getConstructor=s(e)},serverRender:function(e,t,n){var r=this.getConstructor(t),u=o.createElement(r,n);return a[e](u)},mountComponents:function(e){for(var t=v,n=t.findDOMNodes(e),r=0;r<n.length;++r){var a=n[r],u=a.getAttribute(t.CLASS_NAME_ATTR),c=t.getConstructor(u),i=a.getAttribute(t.PROPS_ATTR),d=i&&JSON.parse(i),s=a.getAttribute(t.RENDER_ATTR),p=a.getAttribute(t.CACHE_ID_ATTR),f=a.hasAttribute(t.TURBOLINKS_PERMANENT_ATTR);if(!c){var E="Cannot find component: '"+u+"'";throw console&&console.log&&console.log("%c[react-rails] %c"+E+" for element","font-weight: bold","",a),new Error(E+". Make sure your component is available to render.")}var h=this.components[p];void 0===h&&(h=o.createElement(c,d),f&&(this.components[p]=h)),h=s&&_()?l(a,h):this.findOrCreateRoot(a).render(h)}},unmountComponents:function(e){for(var t=v.findDOMNodes(e),n=0;n<t.length;++n){var o=t[n];f?this.unmountRoot(o):r.unmountComponentAtNode(o)}},detectEvents:function(){u(this)},findOrCreateRoot:function(e){var t=this.findRoot(e);return t||(t=p(e),f&&this.roots.push({node:e,root:t})),t},findRoot:function(e){if(f){var t=this.roots.find((function(t){return t.node&&t.node===e}));return t?t.root:void 0}},unmountRoot:function(e){var t=this.findRoot(e);t&&(t.unmount(),this.roots=this.roots.filter((function(t){return t.node!==e})))},handleMount:function(e){var t=void 0;e&&e.target&&(t=e.target),v.mountComponents(t)},handleUnmount:function(e){var t=void 0;e&&e.target&&(t=e.target),v.unmountComponents(t)}};"undefined"!=typeof window&&v.detectEvents(),self.ReactRailsUJS=v,e.exports=v},230:(e,t,n)=>{var o=n(528),r=n(921),a=n(228),u=n(724),c=n(968);e.exports=function(e){e.handleEvent&&("undefined"!=typeof Turbolinks&&void 0!==Turbolinks.EVENTS&&c.teardown(e),a.teardown(e),u.teardown(e),r.teardown(e),o.teardown(e)),"addEventListener"in window?(e.handleEvent=function(e,t){document.addEventListener(e,t)},e.removeEvent=function(e,t){document.removeEventListener(e,t)}):(e.handleEvent=function(e,t){window.attachEvent(e,t)},e.removeEvent=function(e,t){window.detachEvent(e,t)}),"undefined"!=typeof Turbolinks&&Turbolinks.supported?void 0!==Turbolinks.EVENTS?c.setup(e):void 0!==Turbolinks.controller?a.setup(e):u.setup(e):"undefined"!=typeof $&&"function"==typeof $.pjax?r.setup(e):o.setup(e)}},528:e=>{e.exports={setup:function(e){"addEventListener"in window?e.handleEvent("DOMContentLoaded",e.handleMount):e.handleEvent("onload",e.handleMount)},teardown:function(e){e.removeEvent("DOMContentLoaded",e.handleMount),e.removeEvent("onload",e.handleMount)}}},921:e=>{e.exports={setup:function(e){e.handleEvent("ready",e.handleMount),e.handleEvent("pjax:end",e.handleMount),e.handleEvent("pjax:beforeReplace",e.handleUnmount)},teardown:function(e){e.removeEvent("ready",e.handleMount),e.removeEvent("pjax:end",e.handleMount),e.removeEvent("pjax:beforeReplace",e.handleUnmount)}}},228:e=>{e.exports={setup:function(e){e.handleEvent("turbolinks:load",e.handleMount)},teardown:function(e){e.removeEvent("turbolinks:load",e.handleMount)}}},968:e=>{e.exports={setup:function(e){e.handleEvent(Turbolinks.EVENTS.CHANGE,e.handleMount),e.handleEvent(Turbolinks.EVENTS.BEFORE_UNLOAD,e.handleUnmount)},teardown:function(e){e.removeEvent(Turbolinks.EVENTS.CHANGE,e.handleMount),e.removeEvent(Turbolinks.EVENTS.BEFORE_UNLOAD,e.handleUnmount)}}},724:e=>{e.exports={setup:function(e){Turbolinks.pagesCached(0),e.handleEvent("page:change",e.handleMount),e.handleEvent("page:receive",e.handleUnmount)},teardown:function(e){e.removeEvent("page:change",e.handleMount),e.removeEvent("page:receive",e.handleUnmount)}}},121:function(module){var topLevel="undefined"==typeof window?this:window;module.exports=function(className){var constructor;return constructor=topLevel[className],constructor||(constructor=eval(className)),constructor&&constructor.default&&(constructor=constructor.default),constructor}},831:e=>{e.exports=function(e){return function(t){var n=t.split("."),o=n.shift(),r=n,a=e("./"+o);return r.forEach((function(e){a=a[e]})),a.__esModule&&(a=a.default),a}}},37:(e,t,n)=>{var o=n(121),r=n(831);e.exports=function(e){var t=r(e);return function(e){var n;try{n=t(e)}catch(t){try{n=o(e)}catch(e){console.error(t),console.error(e)}}return n}}},39:(e,t,n)=>{var o=n(121),r=n(831);e.exports=function(e){var t=e.map((e=>r(e)));return function(e){var n;try{var r,a,u=0;do{r=t[u];try{n=r(e)}catch(e){a||(a=e)}u+=1}while(u<t.length);if(!n)throw a}catch(a){try{n=o(e)}catch(e){console.error(a),console.error(e)}}return n}}},198:(e,t,n)=>{"use strict";n.r(t),n.d(t,{createReactRootLike:()=>_,reactHydrate:()=>s,supportsHydration:()=>d});var o=n(156),r=n.n(o),a=n(613),u=n.n(a);let c=r();if(u())try{c=n(634)}catch(e){c=r()}const i=c;function d(){return"function"==typeof i.hydrate||"function"==typeof i.hydrateRoot}function s(e,t){return"function"==typeof i.hydrateRoot?i.hydrateRoot(e,t):i.hydrate(t,e)}function _(e){return u()?i.createRoot(e):function(e){return{render:t=>i.render(t,e)}}(e)}},613:(e,t,n)=>{var o,r=n(156);o=void 0!==r&&(r.version.split(".")[0]||16)>=18,e.exports=o},787:e=>{"use strict";e.exports=__WEBPACK_EXTERNAL_MODULE__787__},156:e=>{"use strict";e.exports=__WEBPACK_EXTERNAL_MODULE__156__},997:e=>{"use strict";e.exports=__WEBPACK_EXTERNAL_MODULE__997__}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__(10);return __webpack_exports__})()));
@@ -256,14 +256,20 @@ module React
256
256
  def detect_template_extension
257
257
  if options[:coffee]
258
258
  "js.jsx.coffee"
259
+ elsif options[:ts] && es6_enabled?
260
+ "es6.tsx"
259
261
  elsif options[:ts]
260
262
  "js.jsx.tsx"
261
- elsif options[:es6] || shakapacker?
263
+ elsif es6_enabled?
262
264
  "es6.jsx"
263
265
  else
264
266
  "js.jsx"
265
267
  end
266
268
  end
269
+
270
+ def es6_enabled?
271
+ options[:es6] || shakapacker?
272
+ end
267
273
  end
268
274
  end
269
275
  end
@@ -103,8 +103,19 @@ module React
103
103
  ReactRailsUJS.useContext(componentRequireContext);
104
104
  JS
105
105
 
106
+ def require_package_json_gem
107
+ require "bundler/inline"
108
+
109
+ gemfile(true) { gem "package_json" }
110
+
111
+ puts "using package_json v#{PackageJson::VERSION}"
112
+ end
113
+
106
114
  def setup_react_shakapacker
107
- `yarn add react_ujs`
115
+ require_package_json_gem
116
+
117
+ PackageJson.read.manager.add(["react_ujs"])
118
+
108
119
  if manifest.exist?
109
120
  append_file(manifest, SHAKAPACKER_SETUP_UJS)
110
121
  else
@@ -0,0 +1,24 @@
1
+ <%= file_header %>
2
+ interface I<%= component_name %>Props {
3
+ <% if attributes.size > 0 -%>
4
+ <% attributes.each do |attribute| -%>
5
+ <% if attribute[:union] -%>
6
+ <%= attribute[:name].camelize(:lower) %>: <%= attribute[:name].titleize %>;
7
+ <% else -%>
8
+ <%= attribute[:name].camelize(:lower) %>: <%= attribute[:type] %>;
9
+ <% end -%>
10
+ <% end -%>
11
+ <% end -%>
12
+ }
13
+
14
+ const <%= component_name %> = (props: I<%= component_name %>Props) => {
15
+ return (
16
+ <React.Fragment>
17
+ <% attributes.each do |attribute| -%>
18
+ <%= attribute[:name].titleize %>: {props.<%= attribute[:name].camelize(:lower) %>}
19
+ <% end -%>
20
+ </React.Fragment>
21
+ )
22
+ }
23
+
24
+ <%= file_footer %>
@@ -4,6 +4,6 @@ module React
4
4
  module Rails
5
5
  # If you change this, make sure to update VERSIONS.md
6
6
  # and republish the UJS by updating package.json and `bundle exec rake ujs:publish`
7
- VERSION = "3.1.1"
7
+ VERSION = "3.2.1"
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: react-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.1
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul O’Shannessy
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-08-16 00:00:00.000000000 Z
14
+ date: 2024-05-17 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: appraisal
@@ -209,6 +209,68 @@ dependencies:
209
209
  - - ">="
210
210
  - !ruby/object:Gem::Version
211
211
  version: '0'
212
+ - !ruby/object:Gem::Dependency
213
+ name: package_json
214
+ requirement: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ type: :development
220
+ prerelease: false
221
+ version_requirements: !ruby/object:Gem::Requirement
222
+ requirements:
223
+ - - ">="
224
+ - !ruby/object:Gem::Version
225
+ version: '0'
226
+ - !ruby/object:Gem::Dependency
227
+ name: rails
228
+ requirement: !ruby/object:Gem::Requirement
229
+ requirements:
230
+ - - "~>"
231
+ - !ruby/object:Gem::Version
232
+ version: 7.0.7
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: 7.0.7.2
236
+ type: :development
237
+ prerelease: false
238
+ version_requirements: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - "~>"
241
+ - !ruby/object:Gem::Version
242
+ version: 7.0.7
243
+ - - ">="
244
+ - !ruby/object:Gem::Version
245
+ version: 7.0.7.2
246
+ - !ruby/object:Gem::Dependency
247
+ name: turbo-rails
248
+ requirement: !ruby/object:Gem::Requirement
249
+ requirements:
250
+ - - ">="
251
+ - !ruby/object:Gem::Version
252
+ version: '0'
253
+ type: :development
254
+ prerelease: false
255
+ version_requirements: !ruby/object:Gem::Requirement
256
+ requirements:
257
+ - - ">="
258
+ - !ruby/object:Gem::Version
259
+ version: '0'
260
+ - !ruby/object:Gem::Dependency
261
+ name: minitest-retry
262
+ requirement: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - ">="
265
+ - !ruby/object:Gem::Version
266
+ version: '0'
267
+ type: :development
268
+ prerelease: false
269
+ version_requirements: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - ">="
272
+ - !ruby/object:Gem::Version
273
+ version: '0'
212
274
  - !ruby/object:Gem::Dependency
213
275
  name: connection_pool
214
276
  requirement: !ruby/object:Gem::Requirement
@@ -302,6 +364,7 @@ files:
302
364
  - lib/generators/react/component_generator.rb
303
365
  - lib/generators/react/install_generator.rb
304
366
  - lib/generators/templates/component.es6.jsx
367
+ - lib/generators/templates/component.es6.tsx
305
368
  - lib/generators/templates/component.js.jsx
306
369
  - lib/generators/templates/component.js.jsx.coffee
307
370
  - lib/generators/templates/component.js.jsx.tsx