|
1 | 1 | # Using ReactOnRails in JavaScript |
2 | 2 |
|
3 | | -You can easily render React components in your JavaScript with `render` method that returns a [reference to the component](https://react.dev/reference/react-dom/render#returns) (virtual DOM element). |
| 3 | +You can easily render React components in your JavaScript with the `render` method. Under React 18+, it returns a React root. Under React 16/17, legacy return values vary by render or hydrate path, such as a component instance, an element, or `void`. |
4 | 4 |
|
5 | 5 | ```js |
6 | 6 | /** |
7 | 7 | * ReactOnRails.render("HelloWorldApp", {name: "Stranger"}, 'app'); |
8 | 8 | * |
9 | | - * Does this: |
| 9 | + * Under React 16/17, this is equivalent to: |
10 | 10 | * ReactDOM.render(React.createElement(HelloWorldApp, {name: "Stranger"}), |
11 | 11 | * document.getElementById('app')) |
12 | 12 | * |
| 13 | + * Under React 18+, it uses: |
| 14 | + * const root = ReactDOMClient.createRoot(document.getElementById('app')); |
| 15 | + * root.render(React.createElement(HelloWorldApp, {name: "Stranger"})); |
| 16 | + * return root; |
| 17 | + * |
13 | 18 | * @param name Name of your registered component |
14 | 19 | * @param props Props to pass to your component |
15 | 20 | * @param domNodeId |
16 | 21 | * @param hydrate [optional] Pass truthy to update server rendered html. Default is falsy |
17 | | - * @returns {virtualDomElement} Reference to your component's backing instance |
| 22 | + * @returns {Root|Component|Element|void} React root in React 18+, or legacy return values in |
| 23 | + * React 16/17 depending on the render or hydrate path |
18 | 24 | */ |
19 | 25 | ReactOnRails.render(componentName, props, domNodeId); |
20 | 26 | ``` |
21 | 27 |
|
22 | 28 | ## Why do we need this? |
23 | 29 |
|
24 | | -Imagine that we have some event with jQuery, it allows us to set component state manually. |
| 30 | +Imagine that some external JavaScript decides when a component should mount with the current value. |
25 | 31 |
|
26 | 32 | ```html |
27 | 33 | <input id="input" type="range" min="0" max="100" /> |
28 | 34 | <div id="root"></div> |
29 | 35 |
|
30 | 36 | <script> |
31 | | - var input = $('#input'); |
32 | | - var component = ReactOnRails.render('componentName', { value: input.val() }, 'root'); |
33 | | -
|
34 | | - input.on('change', function (e) { |
35 | | - component.setState({ value: input.val() }); |
36 | | - }); |
| 37 | + const input = document.getElementById('input'); |
| 38 | + ReactOnRails.render('componentName', { value: input.value }, 'root'); |
37 | 39 | </script> |
38 | 40 | ``` |
| 41 | + |
| 42 | +For subsequent updates on the same DOM node, let the mounted React component manage its own |
| 43 | +state or props flow. The public `ReactOnRails.render` API does not deduplicate repeated calls, |
| 44 | +so calling it on `#root` will invoke React unless you unmount or replace that node first. |
0 commit comments