Skip to content

Commit d20da7f

Browse files
committed
Let the dummy run under React 16
1 parent 3482b7f commit d20da7f

File tree

6 files changed

+139
-4
lines changed

6 files changed

+139
-4
lines changed

eslint.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ const config = tsEslint.config([
184184
'@typescript-eslint/restrict-template-expressions': 'off',
185185
},
186186
},
187+
{
188+
files: ['**/app-react16/**/*'],
189+
rules: {
190+
'react/no-deprecated': 'off',
191+
},
192+
},
187193
// must be the last config in the array
188194
// https://github.com/prettier/eslint-plugin-prettier?tab=readme-ov-file#configuration-new-eslintconfigjs
189195
prettierRecommended,

knip.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const config: KnipConfig = {
5454
// Declaring this as webpack.config instead doesn't work correctly
5555
'config/webpack/webpack.config.js',
5656
],
57+
ignore: ['**/app-react16/**/*'],
5758
project: ['**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!', 'config/webpack/*.js'],
5859
paths: {
5960
'Assets/*': ['client/app/assets/*'],

script/convert

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ def gsub_file_content(path, old_content, new_content)
88
File.binwrite(path, content)
99
end
1010

11-
old_config = File.expand_path("../spec/dummy/config/shakapacker.yml", __dir__)
12-
new_config = File.expand_path("../spec/dummy/config/webpacker.yml", __dir__)
11+
def move(old_path, new_path)
12+
old_path = File.expand_path(old_path, __dir__)
13+
new_path = File.expand_path(new_path, __dir__)
14+
File.rename(old_path, new_path)
15+
end
1316

14-
File.rename(old_config, new_config)
17+
move("../spec/dummy/config/shakapacker.yml", "../spec/dummy/config/webpacker.yml")
1518

1619
# Shakapacker
1720
gsub_file_content("../Gemfile.development_dependencies", /gem "shakapacker", "[^"]*"/, 'gem "shakapacker", "6.6.0"')
@@ -31,13 +34,18 @@ gsub_file_content("../package.json", %r{"@testing-library/react": "[^"]*",}, "")
3134
# Switch to the oldest supported React version
3235
gsub_file_content("../package.json", /"react": "[^"]*",/, '"react": "16.0.0",')
3336
gsub_file_content("../package.json", /"react-dom": "[^"]*",/, '"react-dom": "16.0.0",')
34-
# TODO: can't change React version in spec/dummy as well, would need a separate react-16-dummy instead
37+
gsub_file_content("../spec/dummy/package.json", /"react": "[^"]*",/, '"react": "16.0.0",')
38+
gsub_file_content("../spec/dummy/package.json", /"react-dom": "[^"]*",/, '"react-dom": "16.0.0",')
3539
gsub_file_content(
3640
"../package.json",
3741
"jest node_package/tests",
3842
'jest node_package/tests --testPathIgnorePatterns=\".*(RSC|stream|serverRenderReactComponent).*\"'
3943
)
4044
gsub_file_content("../tsconfig.json", "react-jsx", "react")
45+
# Find all files under app-react16 and replace the React 19 versions
46+
Dir.glob(File.expand_path("../spec/dummy/**/app-react16/**/*.*", __dir__)).each do |file|
47+
move(file, file.gsub("-react16", ""))
48+
end
4149

4250
gsub_file_content("../spec/dummy/config/webpack/commonWebpackConfig.js", /generateWebpackConfig(\(\))?/,
4351
"webpackConfig")
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
4+
export default (props, _railsContext, domNodeId) => {
5+
const reactElement = (
6+
<div>
7+
<h1 id="manual-render">Manual Render Example</h1>
8+
<p>If you can see this, you can register renderer functions.</p>
9+
</div>
10+
);
11+
12+
const domNode = document.getElementById(domNodeId);
13+
if (props.prerender) {
14+
ReactDOM.hydrate(reactElement, domNode);
15+
} else {
16+
ReactDOM.render(reactElement, domNode);
17+
}
18+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Top level component for client side.
2+
// Compare this to the ./ServerApp.jsx file which is used for server side rendering.
3+
// NOTE: these are basically the same, but they are shown here
4+
5+
import React from 'react';
6+
import { combineReducers, applyMiddleware, createStore } from 'redux';
7+
import { Provider } from 'react-redux';
8+
import thunkMiddleware from 'redux-thunk';
9+
import ReactDOM from 'react-dom';
10+
11+
import reducers from '../../app/reducers/reducersIndex';
12+
import composeInitialState from '../../app/store/composeInitialState';
13+
14+
import HelloWorldContainer from '../../app/components/HelloWorldContainer';
15+
16+
/*
17+
* Export a function that takes the props and returns a ReactComponent.
18+
* This is used for the client rendering hook after the page html is rendered.
19+
* React will see that the state is the same and not do anything.
20+
*
21+
*/
22+
export default (props, railsContext, domNodeId) => {
23+
const render = props.prerender ? ReactDOM.hydrate : ReactDOM.render;
24+
// eslint-disable-next-line no-param-reassign
25+
delete props.prerender;
26+
27+
const combinedReducer = combineReducers(reducers);
28+
const combinedProps = composeInitialState(props, railsContext);
29+
30+
// This is where we'll put in the middleware for the async function. Placeholder.
31+
// store will have helloWorldData as a top level property
32+
const store = createStore(combinedReducer, combinedProps, applyMiddleware(thunkMiddleware));
33+
34+
// renderApp is a function required for hot reloading. see
35+
// https://github.com/retroalgic/react-on-rails-hot-minimal/blob/master/client/src/entry.js
36+
37+
// Provider uses this.props.children, so we're not typical React syntax.
38+
// This allows redux to add additional props to the HelloWorldContainer.
39+
const renderApp = (Komponent) => {
40+
const element = (
41+
<Provider store={store}>
42+
<Komponent />
43+
</Provider>
44+
);
45+
46+
render(element, document.getElementById(domNodeId));
47+
};
48+
49+
renderApp(HelloWorldContainer);
50+
51+
if (module.hot) {
52+
module.hot.accept(['../reducers/reducersIndex', '../components/HelloWorldContainer'], () => {
53+
store.replaceReducer(combineReducers(reducers));
54+
renderApp(HelloWorldContainer);
55+
});
56+
}
57+
};
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Top level component for the client side.
2+
// Compare this to the ./ReduxSharedStoreApp.server.jsx file which is used for server side rendering.
3+
4+
import React from 'react';
5+
import { Provider } from 'react-redux';
6+
import ReactOnRails from 'react-on-rails/client';
7+
import ReactDOM from 'react-dom';
8+
9+
import HelloWorldContainer from '../../app/components/HelloWorldContainer';
10+
11+
/*
12+
* Export a function that returns a ReactComponent, depending on a store named SharedReduxStore.
13+
* This is used for the client rendering hook after the page html is rendered.
14+
* React will see that the state is the same and not do anything.
15+
*/
16+
export default (props, _railsContext, domNodeId) => {
17+
const render = props.prerender ? ReactDOM.hydrate : ReactDOM.render;
18+
// eslint-disable-next-line no-param-reassign
19+
delete props.prerender;
20+
21+
// This is where we get the existing store.
22+
const store = ReactOnRails.getStore('SharedReduxStore');
23+
24+
// renderApp is a function required for hot reloading. see
25+
// https://github.com/retroalgic/react-on-rails-hot-minimal/blob/master/client/src/entry.js
26+
27+
// Provider uses this.props.children, so we're not typical React syntax.
28+
// This allows redux to add additional props to the HelloWorldContainer.
29+
const renderApp = (Component) => {
30+
const element = (
31+
<Provider store={store}>
32+
<Component />
33+
</Provider>
34+
);
35+
render(element, document.getElementById(domNodeId));
36+
};
37+
38+
renderApp(HelloWorldContainer);
39+
40+
if (module.hot) {
41+
module.hot.accept(['../components/HelloWorldContainer'], () => {
42+
renderApp(HelloWorldContainer);
43+
});
44+
}
45+
};

0 commit comments

Comments
 (0)