Skip to content

Commit db1c0fd

Browse files
justin808claude
andcommitted
Update spec/dummy for React 19 compatibility
- Upgrade react-redux from ^8.0.2 to ^9.2.0 for React 19 support - Upgrade redux from ^4.0.1 to ^5.0.1 (required by react-redux 9.x) - Upgrade redux-thunk from ^2.2.0 to ^3.1.0 (required by redux 5.x) - Replace react-helmet@^6.1.0 with @dr.pogodin/react-helmet@^3.0.4 (thread-safe React 19 compatible fork) Code changes: - Update redux-thunk imports to use named export: { thunk } - Update react-helmet SSR to use HelmetProvider with context prop - Remove @types/react-helmet (new package has built-in types) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent e8442f8 commit db1c0fd

File tree

10 files changed

+84
-104
lines changed

10 files changed

+84
-104
lines changed

react_on_rails/spec/dummy/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ GEM
345345
rubyzip (>= 1.2.2, < 3.0)
346346
websocket (~> 1.0)
347347
semantic_range (3.1.0)
348-
shakapacker (9.3.0)
348+
shakapacker (9.4.0)
349349
activesupport (>= 5.2)
350350
package_json
351351
rack-proxy (>= 0.6.1)
@@ -461,7 +461,7 @@ DEPENDENCIES
461461
sass-rails (~> 6.0)
462462
sdoc
463463
selenium-webdriver (= 4.9.0)
464-
shakapacker (= 9.3.0)
464+
shakapacker (= 9.4.0)
465465
spring (~> 4.0)
466466
sprockets (~> 4.0)
467467
sqlite3 (~> 1.6)

react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import React from 'react';
66
import { combineReducers, applyMiddleware, createStore } from 'redux';
77
import { Provider } from 'react-redux';
8-
import thunkMiddleware from 'redux-thunk';
8+
import { thunk } from 'redux-thunk';
99
import ReactDOM from 'react-dom';
1010

1111
import reducers from '../../app/reducers/reducersIndex';
@@ -29,7 +29,7 @@ export default (props, railsContext, domNodeId) => {
2929

3030
// This is where we'll put in the middleware for the async function. Placeholder.
3131
// store will have helloWorldData as a top level property
32-
const store = createStore(combinedReducer, combinedProps, applyMiddleware(thunkMiddleware));
32+
const store = createStore(combinedReducer, combinedProps, applyMiddleware(thunk));
3333

3434
// renderApp is a function required for hot reloading. see
3535
// https://github.com/retroalgic/react-on-rails-hot-minimal/blob/master/client/src/entry.js

react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React from 'react';
2-
import { Helmet } from 'react-helmet';
2+
import { Helmet } from '@dr.pogodin/react-helmet';
33
import HelloWorld from '../startup/HelloWorld';
44

5+
// Note: This component expects to be wrapped in a HelmetProvider by its parent.
6+
// For client-side rendering, wrap in HelmetProvider at the app root.
7+
// For server-side rendering, the server entry point provides the HelmetProvider.
58
const ReactHelmet = (props) => (
69
<div>
710
<Helmet>

react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Top level component for simple client side only rendering
22
import React from 'react';
33
import { renderToString } from 'react-dom/server';
4-
import { Helmet } from 'react-helmet';
5-
import ReactHelmet from '../components/ReactHelmet';
4+
import { Helmet, HelmetProvider } from '@dr.pogodin/react-helmet';
5+
import HelloWorld from './HelloWorld';
66

77
/*
88
* Export a function that takes the props and returns an object with { renderedHtml }
@@ -16,12 +16,27 @@ import ReactHelmet from '../components/ReactHelmet';
1616
* the function could get the property of `.renderFunction = true` added to it.
1717
*/
1818
export default (props, _railsContext) => {
19-
const componentHtml = renderToString(<ReactHelmet {...props} />);
20-
const helmet = Helmet.renderStatic();
19+
// For server-side rendering with @dr.pogodin/react-helmet, we pass a context object
20+
// to HelmetProvider to capture the helmet data per-request (thread-safe)
21+
const helmetContext = {};
22+
23+
const componentHtml = renderToString(
24+
<HelmetProvider context={helmetContext}>
25+
<div>
26+
<Helmet>
27+
<title>Custom page title</title>
28+
</Helmet>
29+
Props: {JSON.stringify(props)}
30+
<HelloWorld {...props} />
31+
</div>
32+
</HelmetProvider>,
33+
);
34+
35+
const { helmet } = helmetContext;
2136

2237
const renderedHtml = {
2338
componentHtml,
24-
title: helmet.title.toString(),
39+
title: helmet ? helmet.title.toString() : '',
2540
};
2641

2742
// Note that this function returns an Object for server rendering.

react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// function. The point of this is to provide a good error.
44
import React from 'react';
55
import { renderToString } from 'react-dom/server';
6-
import { Helmet } from 'react-helmet';
6+
import { HelmetProvider } from '@dr.pogodin/react-helmet';
77
import ReactHelmet from '../components/ReactHelmet';
88

99
/*
@@ -18,12 +18,17 @@ import ReactHelmet from '../components/ReactHelmet';
1818
* Alternately, the function could get the property of `.renderFunction = true` added to it.
1919
*/
2020
export default (props) => {
21-
const componentHtml = renderToString(<ReactHelmet {...props} />);
22-
const helmet = Helmet.renderStatic();
21+
const helmetContext = {};
22+
const componentHtml = renderToString(
23+
<HelmetProvider context={helmetContext}>
24+
<ReactHelmet {...props} />
25+
</HelmetProvider>,
26+
);
27+
const { helmet } = helmetContext;
2328

2429
const renderedHtml = {
2530
componentHtml,
26-
title: helmet.title.toString(),
31+
title: helmet ? helmet.title.toString() : '',
2732
};
2833
return { renderedHtml };
2934
};

react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import React from 'react';
66
import { combineReducers, applyMiddleware, createStore } from 'redux';
77
import { Provider } from 'react-redux';
8-
import thunkMiddleware from 'redux-thunk';
8+
import { thunk } from 'redux-thunk';
99
import ReactDOMClient from 'react-dom/client';
1010

1111
import reducers from '../reducers/reducersIndex';
@@ -34,7 +34,7 @@ export default (props, railsContext, domNodeId) => {
3434

3535
// This is where we'll put in the middleware for the async function. Placeholder.
3636
// store will have helloWorldData as a top level property
37-
const store = createStore(combinedReducer, combinedProps, applyMiddleware(thunkMiddleware));
37+
const store = createStore(combinedReducer, combinedProps, applyMiddleware(thunk));
3838

3939
// renderApp is a function required for hot reloading. see
4040
// https://github.com/retroalgic/react-on-rails-hot-minimal/blob/master/client/src/entry.js

react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import React from 'react';
77
import { combineReducers, applyMiddleware, createStore } from 'redux';
88
import { Provider } from 'react-redux';
9-
import middleware from 'redux-thunk';
9+
import { thunk } from 'redux-thunk';
1010

1111
// Uses the index
1212
import reducers from '../reducers/reducersIndex';
@@ -28,7 +28,7 @@ export default (props, railsContext) => {
2828

2929
// This is where we'll put in the middleware for the async function. Placeholder.
3030
// store will have helloWorldData as a top level property
31-
const store = applyMiddleware(middleware)(createStore)(combinedReducer, combinedProps);
31+
const store = applyMiddleware(thunk)(createStore)(combinedReducer, combinedProps);
3232

3333
// Provider uses the this.props.children, so we're not typical React syntax.
3434
// This allows redux to add additional props to the HelloWorldContainer.

react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { combineReducers, applyMiddleware, createStore } from 'redux';
2-
import middleware from 'redux-thunk';
2+
import { thunk } from 'redux-thunk';
33

44
import reducers from '../reducers/reducersIndex';
55

@@ -12,5 +12,5 @@ export default (props, railsContext) => {
1212
delete props.prerender;
1313
const combinedReducer = combineReducers(reducers);
1414
const newProps = { ...props, railsContext };
15-
return applyMiddleware(middleware)(createStore)(combinedReducer, newProps);
15+
return applyMiddleware(thunk)(createStore)(combinedReducer, newProps);
1616
};

react_on_rails/spec/dummy/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
"prop-types": "^15.7.2",
2121
"react": "^19.0.0",
2222
"react-dom": "^19.0.0",
23-
"react-helmet": "^6.1.0",
23+
"@dr.pogodin/react-helmet": "^3.0.4",
2424
"react-on-rails": "link:.yalc/react-on-rails",
25-
"react-redux": "^8.0.2",
25+
"react-redux": "^9.2.0",
2626
"react-router-dom": "^6.0.0",
27-
"redux": "^4.0.1",
28-
"redux-thunk": "^2.2.0",
27+
"redux": "^5.0.1",
28+
"redux-thunk": "^3.1.0",
2929
"regenerator-runtime": "^0.13.4"
3030
},
3131
"devDependencies": {
@@ -38,7 +38,6 @@
3838
"@rescript/react": "^0.13.0",
3939
"@types/react": "^19.0.0",
4040
"@types/react-dom": "^19.0.0",
41-
"@types/react-helmet": "^6.1.5",
4241
"babel-loader": "8.2.4",
4342
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
4443
"compression-webpack-plugin": "9",

0 commit comments

Comments
 (0)