Skip to content

Commit a44cfb2

Browse files
coopersamueljustin808
authored andcommitted
Add option or ReactOnRails.render of hydrate (#1159)
To support React v16, updated API for ReactOnRails.render(name, props, domNodeId, hydrate) { * Added 3rd @param hydrate Pass truthy to update server rendered html. Default is falsey Any truthy values calls hydrate rather than render Other updates: * upgraded react and react DOM, fixed breaking test * updated all minor and patch release packages * updated eslint and flow, fixed a few eslint errors, ignored a flow error added a few rules in eslintrc * updated redux, no broken tests * updated tap-spec and release-it * updated dummy apps gemfile, specified version for miniracer * poltergeist removal * Updates to spec/dummy for new packages * add prettier, but not enforcing * Change String.match? to =~ b/c Can't use match? on Ruby 2.2. Uncomment when Ruby 2.4 is used for all test platforms
1 parent 18e7840 commit a44cfb2

File tree

79 files changed

+5456
-3264
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+5456
-3264
lines changed

.eslintrc

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
---
2-
extends: eslint-config-shakacode
2+
extends:
3+
- eslint-config-shakacode
4+
- prettier
5+
- prettier/react
36

47
plugins:
5-
- react
8+
- prettier
69

710
globals:
811
__DEBUG_SERVER_ERRORS__: true
@@ -15,6 +18,9 @@ env:
1518

1619
rules:
1720
no-console: 0
21+
function-paren-newline: 0
22+
object-curly-newline: 0
23+
1824

1925
# https://github.com/benmosher/eslint-plugin-import/issues/340
2026
import/no-extraneous-dependencies: 0

.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

.prettierrc

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
printWidth: 110
2+
tabWidth: 2
3+
useTabs: false
4+
semi: true
5+
singleQuote: true
6+
trailingComma: all
7+
bracketSpacing: true
8+
jsxBracketSameLine: false
9+
parser: flow
10+
11+
overrides:
12+
- files: "*.@(css|scss)"
13+
options:
14+
parser: css
15+
singleQuote: false
16+
printWidth: 120
17+
- files: "*.@(json)"
18+
options:
19+
parser: json
20+
printWidth: 100

CONTRIBUTING.md

+1-9
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,6 @@ _Note: running `npm i` automatically builds the npm package before installing. H
127127
### Prereqs
128128
After checking out the repo, making sure you have rvm and nvm setup (setup ruby and node), cd to `spec/dummy` and run `bin/setup` to install ruby dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
129129

130-
Additionally, our RSpec tests use the poltergeist web driver. You will need to install the phantomjs node module:
131-
132-
```sh
133-
yarn global add phantomjs-prebuilt
134-
```
135-
136-
Note this *must* be installed globally for the dummy test project rspec runner to see it properly.
137-
138130
### Local Node Package
139131
Because the example and dummy apps rely on the react-on-rails node package, they should link directly to your local version to pick up any changes you may have made to that package. To achieve this, switch to the dummy app's root directory and run this command below which runs something like [this script](spec/dummy/package.json#L14)
140132

@@ -171,7 +163,7 @@ spec/dummy.
171163

172164
```sh
173165
# Optionally change default selenium_firefox driver
174-
export DRIVER=poltergeist
166+
export DRIVER=selenium_firefox
175167
cd react_on_rails/
176168
yarn run dummy:spec
177169
```

Gemfile

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ gem "capybara"
3232
gem "capybara-screenshot"
3333
gem "chromedriver-helper"
3434
gem "launchy"
35-
gem "poltergeist"
3635
gem "rspec-rails"
3736
gem "rspec-retry"
3837
gem "selenium-webdriver"

Gemfile.rails32

-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ group :test do
6565
gem "chromedriver-helper"
6666
gem "generator_spec"
6767
gem "launchy"
68-
gem "poltergeist"
6968
gem "rspec-rails"
7069
gem "rspec-retry"
7170
gem "selenium-webdriver"

docs/additional-reading/images.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const assetLoaderRules = [
3939

4040

4141

42-
A full example can be found at [spec/dummy/client/app/components/ImageExample/ImageExample.js](../../spec/dummy/client/app/components/ImageExample/ImageExample.js)
42+
A full example can be found at [spec/dummy/client/app/components/ImageExample/ImageExample.jsx](../../spec/dummy/client/app/components/ImageExample/ImageExample.jsx)
4343

4444
You are free to use images either in image tags or as background images in SCSS files. You can
4545
use a "global" location of /client/app/assets/images or a relative path to your JS or SCSS file, as

docs/additional-reading/rails_view_rendering_from_inline_javascript.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ You can easily render React components in your JavaScript with `render` method t
1212
* @param name Name of your registered component
1313
* @param props Props to pass to your component
1414
* @param domNodeId
15+
* @param hydrate [optional] Pass truthy to update server rendered html. Default is falsy
1516
* @returns {virtualDomElement} Reference to your component's backing instance
1617
*/
17-
ReactOnRails.render(componentName, props, elementId)
18+
ReactOnRails.render(componentName, props, domNodeId)
1819
```
1920

2021
## Why do we need this?

docs/api/view-helpers-api.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ adding meta-tags to a page. It is exactly like react_component except for the fo
4141

4242
1. `prerender: true` is automatically added to options, as this method doesn't make sense for
4343
client only rendering.
44-
2. Your JavaScript for server rendering must return an Object for the key `server_rendered_html`.
44+
2. Your JavaScript generator function for server rendering must return an Object rather than a React Component.
4545
3. Your view code must expect an object and not a string.
4646

4747
Here is an example of ERB view code:

docs/misc-pending/code-splitting.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Different markup is generated on the client than on the server. Why does this ha
2121

2222
### The solution
2323

24-
To prevent this, you have to wait until the code chunk is fetched before doing the initial render on the client side. To accomplish this, react on rails allows you to register a renderer. This works just like registering a generator function, except that the function you pass takes three arguments: `renderer(props, railsContext, domNodeId)`, and is responsible for calling `ReactDOM.render` to render the component to the DOM. React on rails will automatically detect when a generator function takes three arguments, and will not call `ReactDOM.render`, instead allowing you to control the initial render yourself.
24+
To prevent this, you have to wait until the code chunk is fetched before doing the initial render on the client side. To accomplish this, react on rails allows you to register a renderer. This works just like registering a generator function, except that the function you pass takes three arguments: `renderer(props, railsContext, domNodeId)`, and is responsible for calling `ReactDOM.render` or `ReactDOM.hydrate` to render the component to the DOM. React on rails will automatically detect when a generator function takes three arguments, and will not call `ReactDOM.render` or `ReactDOM.hydrate`, instead allowing you to control the initial render yourself. Note, you have to be careful to call `ReactDOM.hydrate` rather than `ReactDOM.render` if you are are server rendering.
2525

2626
Here's an example of how you might use this in practice:
2727

@@ -115,7 +115,7 @@ See:
115115

116116
- [spec/dummy/client/app/startup/clientRegistration.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/clientRegistration.jsx)
117117
- [spec/dummy/client/app/startup/serverRegistration.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/serverRegistration.jsx)
118-
- [spec/dummy/client/app/startup/DeferredRenderAppRenderer.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/DeferredRenderAppRenderer.jsx) <-- Code splitting implemented here
118+
- [spec/dummy/client/app/startup/DeferredRenderAppClient](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/DeferredRenderAppClient.jsx)<-- Code splitting implemented here
119119
- [spec/dummy/client/app/startup/DeferredRenderAppServer.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/startup/DeferredRenderAppServer.jsx)
120120
- [spec/dummy/client/app/components/DeferredRender.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/DeferredRender.jsx)
121121
- [spec/dummy/client/app/components/DeferredRenderAsyncPage.jsx](https://github.com/shakacode/react_on_rails/tree/master/spec/dummy/client/app/components/DeferredRenderAsyncPage.jsx)

lib/react_on_rails/helper.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def react_component(component_name, options = {})
136136
# It is exactly like react_component except for the following:
137137
# 1. prerender: true is automatically added, as this method doesn't make sense for client only
138138
# rendering.
139-
# 2. Your JavaScript for server rendering must return an Object for the key server_rendered_html.
139+
# 2. Your JavaScript generator function for server rendering must return an Object rather than a React component.
140140
# 3. Your view code must expect an object and not a string.
141141
#
142142
# Here is an example of the view code:

node_package/src/ReactOnRails.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,16 @@ ctx.ReactOnRails = {
153153
* @param name Name of your registered component
154154
* @param props Props to pass to your component
155155
* @param domNodeId
156+
* @param hydrate Pass truthy to update server rendered html. Default is falsy
156157
* @returns {virtualDomElement} Reference to your component's backing instance
157158
*/
158-
render(name, props, domNodeId) {
159+
render(name, props, domNodeId, hydrate) {
159160
const componentObj = ComponentRegistry.get(name);
160161
const reactElement = createReactElement({ componentObj, props, domNodeId });
161162

163+
const render = hydrate ? ReactDOM.hydrate : ReactDOM.render;
162164
// eslint-disable-next-line react/no-render-return-value
163-
return ReactDOM.render(reactElement, document.getElementById(domNodeId));
165+
return render(reactElement, document.getElementById(domNodeId));
164166
},
165167

166168
/**

node_package/src/buildConsoleReplay.js

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import scriptSanitizedVal from './scriptSanitizedVal';
55

66
export function consoleReplay() {
77
// console.history is a global polyfill used in server rendering.
8+
// $FlowFixMe
89
if (!(console.history instanceof Array)) {
910
return '';
1011
}

node_package/src/clientStartup.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ function renderInit() {
204204
}
205205

206206
export function clientStartup(context) {
207-
const document = context.document;
207+
const { document } = context;
208208

209209
// Check if server rendering
210210
if (!document) {

node_package/src/serverRenderReactComponent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ See https://github.com/shakacode/react_on_rails#renderer-functions`);
4242

4343
if (reactElementOrRouterResult.redirectLocation) {
4444
if (trace) {
45-
const redirectLocation = reactElementOrRouterResult.redirectLocation;
45+
const { redirectLocation } = reactElementOrRouterResult;
4646
const redirectPath = redirectLocation.pathname + redirectLocation.search;
4747
console.log(`\
4848
ROUTER REDIRECT: ${name} to dom node with id: ${domNodeId}, redirect to ${redirectPath}`,

node_package/tests/ReactOnRails.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ test('ReactOnRails render returns a virtual DOM element for component', (assert)
2121
ReactOnRails.register({ R1 });
2222

2323
// eslint-disable-next-line no-underscore-dangle
24-
const actual = ReactOnRails.render('R1', {}, 'root')._reactInternalInstance._currentElement.type;
24+
const actual = ReactOnRails.render('R1', {}, 'root')._reactInternalFiber.type;
2525
assert.deepEqual(actual, R1,
2626
'ReactOnRails render should return a virtual DOM element for component');
2727
});

node_package/tests/buildConsoleReplay.test.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ console.warn.apply(console, ["other message","{\\"c\\":3,\\"d\\":4}"]);`;
6161
test('consoleReplay replays converts script tag inside of object string to be safe ', (assert) => {
6262
assert.plan(1);
6363
console.history = [
64-
{ arguments: ['some message </script><script>alert(\'WTF\')</script>',
65-
{ a: 'Wow</script><script>alert(\'WTF\')</script>', b: 2 }],
64+
{
65+
arguments: [
66+
'some message </script><script>alert(\'WTF\')</script>',
67+
{ a: 'Wow</script><script>alert(\'WTF\')</script>', b: 2 },
68+
],
6669
level: 'log',
6770
},
6871
{ arguments: ['other message', { c: 3, d: 4 }], level: 'warn' },

package-scripts.yml

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
scripts:
2+
lint:
3+
description: Run all linters (eslint, flow)
4+
script: concurrently --prefix "[{name}]" --names "ESLINT" -c "blue,yellow,magenta,orange" "nps eslint"
5+
6+
eslint:
7+
default:
8+
description: Run eslint.
9+
script: eslint . --ext ".js,.jsx"
10+
fix:
11+
description: Run eslint and auto-fix.
12+
script: nps "eslint --fix"
13+
debug:
14+
description: Run eslint in debug mode.
15+
script: DEBUG=eslint:cli-engine nps eslint
16+
17+
format:
18+
default:
19+
description: Format files using prettier.
20+
script: concurrently --prefix "[{name}]" --names "js,json" -c "yellow,magenta,green" "nps format.js" "nps format.json"
21+
listDifferent:
22+
description: Check that all files were formatted using prettier.
23+
script: |
24+
concurrently \
25+
--prefix "[{name}]" \
26+
--names "js,css,json" \
27+
-c "yellow,magenta,green" \
28+
"nps format.js.listDifferent" \
29+
"nps format.json.listDifferent"
30+
js:
31+
default:
32+
description: Run prettier-eslint on JS.
33+
script: prettier "packages/**/*.@(js|jsx)" "spec/dummy/client/app/**/*.@(js|jsx)" "webpack.config.babel.js" "webpack/**/*.js" --write
34+
listDifferent:
35+
description: Check if any JS files would change by running prettier-eslint.
36+
script: prettier "**/*.@(js|jsx)" "webpack.config.babel.js" "webpack/**/*.js" --list-different
37+
json:
38+
default:
39+
description: Run prettier on JSON files.
40+
script: rm -rf packages/vm-renderer/tests/tmp && prettier "**/*.json" --write
41+
listDifferent:
42+
description: Check if any JSON files would change by running prettier-eslint.
43+
script: prettier "**/*.json" "../spec/**/*.json" --list-different
44+
renderer:
45+
description: Starts the node renderer.
46+
script: node renderer.js

package.json

+16-11
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,25 @@
1616
"@babel/types": "^7.0.0",
1717
"babel-loader": "^8.0.2",
1818
"babel-tape-runner": "^3.0.0",
19-
"babelify": "^7.3.0",
19+
"babelify": "^10.0.0",
2020
"blue-tape": "^1.0.0",
2121
"create-react-class": "^15.6.0",
22-
"eslint": "^3.19.0",
23-
"eslint-config-shakacode": "^15.0.0",
22+
"eslint": "^5.7.0",
23+
"eslint-config-prettier": "^3.1.0",
24+
"eslint-config-shakacode": "^16.0.1",
2425
"eslint-plugin-import": "^2.6.1",
25-
"eslint-plugin-jsx-a11y": "^5.1.1",
26+
"eslint-plugin-jsx-a11y": "^6.1.2",
27+
"eslint-plugin-prettier": "^3.0.0",
2628
"eslint-plugin-react": "^7.1.0",
27-
"flow-bin": "^0.51.1",
29+
"flow-bin": "^0.83.0",
2830
"jsdom": "^11.1.0",
2931
"prop-types": "^15.5.10",
30-
"react": "^15.6.1",
31-
"react-dom": "^15.6.1",
32+
"react": "^16.5.2",
33+
"react-dom": "^16.5.2",
3234
"react-transform-hmr": "^1.0.4",
33-
"redux": "^3.7.2",
34-
"release-it": "^2.8.2",
35-
"tap-spec": "^4.1.1",
35+
"redux": "^4.0.1",
36+
"release-it": "^7.6.2",
37+
"tap-spec": "^5.0.0",
3638
"tape": "^4.7.0",
3739
"webpack": "^3.4.1",
3840
"webpack-manifest-plugin": "^1.2.1"
@@ -85,6 +87,9 @@
8587
},
8688
"homepage": "https://github.com/shakacode/react_on_rails#readme",
8789
"dependencies": {
88-
"@babel/runtime-corejs2": "^7.0.0"
90+
"@babel/runtime-corejs2": "^7.0.0",
91+
"nps": "^5.9.3",
92+
"prettier": "^1.14.3",
93+
"prettier-eslint-cli": "^4.7.1"
8994
}
9095
}

spec/dummy/.prettierignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

spec/dummy/.prettierrc

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
printWidth: 110
2+
tabWidth: 2
3+
useTabs: false
4+
semi: true
5+
singleQuote: true
6+
trailingComma: all
7+
bracketSpacing: true
8+
jsxBracketSameLine: false
9+
parser: flow
10+
11+
overrides:
12+
- files: "*.@(css|scss)"
13+
options:
14+
parser: css
15+
singleQuote: false
16+
printWidth: 120
17+
- files: "*.@(json)"
18+
options:
19+
parser: json
20+
printWidth: 100

spec/dummy/Gemfile

-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ group :test do
7171
gem "equivalent-xml", github: "mbklein/equivalent-xml"
7272
gem "generator_spec"
7373
gem "launchy"
74-
gem "poltergeist"
7574
gem "rspec-rails"
7675
gem "rspec-retry"
7776
gem "selenium-webdriver"

spec/dummy/Gemfile.lock

+5-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ GIT
77
PATH
88
remote: ../..
99
specs:
10-
react_on_rails (11.1.1)
10+
react_on_rails (11.1.8)
1111
addressable
1212
connection_pool
1313
execjs (~> 2.5)
@@ -86,7 +86,6 @@ GEM
8686
chromedriver-helper (1.2.0)
8787
archive-zip (~> 0.10)
8888
nokogiri (~> 1.8)
89-
cliver (0.3.2)
9089
coderay (1.1.2)
9190
coffee-rails (4.2.2)
9291
coffee-script (>= 2.2.0)
@@ -130,7 +129,7 @@ GEM
130129
json (2.1.0)
131130
launchy (2.4.3)
132131
addressable (~> 2.3)
133-
libv8 (6.3.292.48.1)
132+
libv8 (6.7.288.46.1)
134133
listen (3.1.5)
135134
rb-fsevent (~> 0.9, >= 0.9.4)
136135
rb-inotify (~> 0.9, >= 0.9.7)
@@ -146,8 +145,8 @@ GEM
146145
mimemagic (0.3.2)
147146
mini_mime (1.0.0)
148147
mini_portile2 (2.3.0)
149-
mini_racer (0.1.15)
150-
libv8 (~> 6.3)
148+
mini_racer (0.2.3)
149+
libv8 (>= 6.3)
151150
minitest (5.11.3)
152151
msgpack (1.2.4)
153152
multi_json (1.13.1)
@@ -157,10 +156,6 @@ GEM
157156
parallel (1.12.1)
158157
parser (2.5.1.2)
159158
ast (~> 2.4.0)
160-
poltergeist (1.18.1)
161-
capybara (>= 2.1, < 4)
162-
cliver (~> 0.3.1)
163-
websocket-driver (>= 0.2.0)
164159
powerpack (0.1.2)
165160
pry (0.11.3)
166161
coderay (~> 1.1.0)
@@ -327,7 +322,6 @@ DEPENDENCIES
327322
launchy
328323
listen
329324
mini_racer
330-
poltergeist
331325
pry
332326
pry-byebug
333327
pry-doc
@@ -352,4 +346,4 @@ DEPENDENCIES
352346
webpacker
353347

354348
BUNDLED WITH
355-
1.16.3
349+
1.16.4

0 commit comments

Comments
 (0)