Skip to content

Conversation

@justin808
Copy link
Member

@justin808 justin808 commented Nov 26, 2025

Summary

Updates spec/dummy dependencies to be compatible with React 19:

Dependency Updates

Package Old Version New Version Reason
react 18.0.0 ^19.0.0 Latest React
react-dom 18.0.0 ^19.0.0 Latest React
react-redux ^8.0.2 ^9.2.0 React 19 support
redux ^4.0.1 ^5.0.1 Required by react-redux 9.x
redux-thunk ^2.2.0 ^3.1.0 Required by redux 5.x
react-helmet ^6.1.0 Replaced with @dr.pogodin/react-helmet@^3.0.4 Thread-safe React 19 fork

Code Changes

  1. redux-thunk imports - Updated from default export to named export:

    • import middleware from 'redux-thunk'import { thunk } from 'redux-thunk'
    • Files: SharedReduxStore.jsx, ReduxApp.server.jsx, ReduxApp.client.jsx
  2. react-helmet migration - Updated to @dr.pogodin/react-helmet:

    • Uses HelmetProvider wrapper (required for both client and server)
    • Server-side uses context prop for thread-safe data capture
    • Files: ReactHelmet.jsx, ReactHelmetApp.server.jsx, ReactHelmetAppBroken.server.jsx, client entry points

Test Plan

  • Integration Tests pass (tests React rendering with new dependencies)
  • Lint passes
  • Manual test: Run spec/dummy app and verify React components render

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Upgraded React to v19 and updated the Redux stack, including thunk middleware.
    • Replaced react-helmet with @dr.pogodin/react-helmet and moved to provider-based helmet handling for client/server rendering.
    • Adjusted loadable client imports to reference JSX client entry points and updated bundler/runtime expectations.
    • Bumped packaging tooling (shakapacker) in development dependencies.
  • Documentation

    • Minor formatting/punctuation fixes in code-splitting docs.
    • Added guidance to commit/push and run local tests to reduce CI failures.

✏️ Tip: You can customize this high-level summary in your review settings.

justin808 and others added 2 commits November 25, 2025 14:19
- 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]>
Add HelmetProvider wrapper to client-side entry points for ReactHelmet
components. The @dr.pogodin/react-helmet package requires HelmetProvider
to wrap all Helmet components, on both server and client sides.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 26, 2025

Walkthrough

Replaces default redux-thunk imports with named thunk, swaps react-helmet for @dr.pogodin/react-helmet and wraps apps/components with HelmetProvider using per-request helmetContext on the server. Bumps dummy package deps (React → 19, Redux → 5, redux-thunk → 3, react-redux → 9) and updates related files.

Changes

Cohort / File(s) Summary
Redux Thunk Migration
react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx, react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx, react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx, react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx
Replace default redux-thunk import (e.g., thunkMiddleware) with named thunk and update applyMiddleware(...) references to use thunk.
React Helmet — Client Wrappers
react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx, react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx, react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx, react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx, react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx, react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx, react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx, react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx, react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
Change imports from react-helmet@dr.pogodin/react-helmet; add HelmetProvider wrappers around rendered components/entry points for client/hydration.
React Helmet — Server Context
react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx, react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx, react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx, react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx, react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx
Replace Helmet.renderStatic() with per-request HelmetProvider + helmetContext; render inside provider and extract helmet fields (link/meta/style/title) from the context with safe fallbacks.
Dependency / Package Updates
react_on_rails/spec/dummy/package.json, react_on_rails_pro/spec/dummy/package.json
Bump dummy dependencies: React 18 → 19, react-dom accordingly; redux → 5, redux-thunk → 3 (named import), react-redux → 9; replace react-helmet with @dr.pogodin/react-helmet; bump shakapacker in pro dummy.
Docs / Views / Minor formatting
react_on_rails_pro/docs/code-splitting-loadable-components.md, react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
Formatting/punctuation tweaks in docs and change server-rendered view client import path to use .jsx.
Misc CONTRIBUTING
CLAUDE.md
Add guidance to commit/push by default and stronger local-testing/CI-avoidance recommendations.
Gemfile dev deps
react_on_rails_pro/Gemfile.development_dependencies
Bump shakapacker 9.3.0 → 9.4.0.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Req as HTTP Request
  participant SSR as Server (renderer)
  participant Provider as HelmetProvider (per-request)
  participant App as React App / Component
  Note over SSR,Provider: per-request helmetContext created and used
  Req->>SSR: incoming page request
  SSR->>Provider: create helmetContext = {}
  SSR->>App: render App inside Provider(context=helmetContext)
  App-->>Provider: components record head data into context
  SSR->>Provider: read helmetContext (title/meta/link/style)
  Provider-->>SSR: extracted head tags
  SSR->>Req: respond with HTML including extracted helmet tags
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus review on:
    • Server files that create/use per-request helmetContext for correctness and safe fallbacks.
    • Client/hydration files to ensure HelmetProvider wrapping matches server render tree.
    • package.json and dev/gemfile bumps for compatibility implications.

Possibly related PRs

Suggested reviewers

  • AbanoubGhadban
  • alexeyr-ci2
  • alexeyr-ci
  • Judahmeek

Poem

🐰 Thunks renamed and helmets set in place,
Contexts cradle titles with gentle grace.
Eighteen hopped to nineteen, packages aligned,
Providers guard the head tags, per-request designed.
A cheerful nibble — render trees refined.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Update spec/dummy for React 19 compatibility' accurately summarizes the primary objective of the pull request, which is updating the dummy application for React 19 compatibility.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jg/react19-compat

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ff7069 and e5051df.

⛔ Files ignored due to path filters (1)
  • react_on_rails_pro/spec/dummy/Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • react_on_rails_pro/Gemfile.development_dependencies (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS ensure files end with a newline character before committing/pushing

Files:

  • react_on_rails_pro/Gemfile.development_dependencies
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG*.md : Use changelog format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` (no hash in PR number)
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG*.md : Use changelog format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` (no hash in PR number)

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails_pro/Gemfile.development_dependencies
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: claude-review
🔇 Additional comments (1)
react_on_rails_pro/Gemfile.development_dependencies (1)

10-10: I'll help you verify the review comment about the shakapacker version bump. Let me search the repository to check version consistency across all Gemfiles.
<function_calls>

#!/bin/bash

Find all shakapacker occurrences and their versions

rg -n "shakapacker" --type ruby


</function_calls>
<function_calls>

#!/bin/bash

Check root Gemfile.development_dependencies for shakapacker

if [ -f "Gemfile.development_dependencies" ]; then
echo "=== Root Gemfile.development_dependencies ==="
cat -n Gemfile.development_dependencies | head -20
fi

Check if react_on_rails_pro file exists and show its content

if [ -f "react_on_rails_pro/Gemfile.development_dependencies" ]; then
echo -e "\n=== react_on_rails_pro/Gemfile.development_dependencies ==="
cat -n react_on_rails_pro/Gemfile.development_dependencies
fi


</function_calls>
<function_calls>

#!/bin/bash

List all Gemfile-related files to understand the structure

echo "=== Gemfile-related files ==="
fd -t f "Gemfile" . | head -20


</function_calls>
<function_calls>

#!/bin/bash

Check for newline at end of react_on_rails_pro/Gemfile.development_dependencies

if [ -f "react_on_rails_pro/Gemfile.development_dependencies" ]; then
echo "File size and final bytes:"
wc -c react_on_rails_pro/Gemfile.development_dependencies
echo "Last character (hex):"
tail -c 1 react_on_rails_pro/Gemfile.development_dependencies | od -A x -t x1z -v
fi


</function_calls>


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Nov 26, 2025

Code Review: React 19 Compatibility Update

I've reviewed this PR and overall it looks solid. The changes correctly update the spec/dummy app to React 19 and handle the necessary dependency migrations. Here's my detailed feedback:


What's Good

1. Dependency Updates Are Correct

  • React 18 → 19: ✅ Uses caret range (^19.0.0) allowing patch updates
  • react-redux 8 → 9: ✅ Required for React 19 support
  • redux 4 → 5: ✅ Required by react-redux 9.x
  • redux-thunk 2 → 3: ✅ Required by redux 5.x
  • react-helmet migration: ✅ Correctly switches to maintained fork

2. Code Changes Are Thorough

  • All redux-thunk imports correctly updated from default to named export
  • HelmetProvider correctly added to all client-side entry points
  • Server-side rendering correctly uses context object for thread-safety
  • Good defensive coding with helmet ? helmet.title.toString() : ''

3. Documentation Added

  • Helpful comments explaining HelmetProvider requirements
  • Clear explanation of thread-safe server-side rendering pattern

⚠️ Potential Issues

1. Inconsistency: ReactHelmetApp.server.jsx Structure Change

In react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx, the component structure was significantly changed:

Before (expected based on component name):

const componentHtml = renderToString(<ReactHelmet {...props} />);

After:

const componentHtml = renderToString(
  <HelmetProvider context={helmetContext}>
    <div>
      <Helmet>
        <title>Custom page title</title>
      </Helmet>
      Props: {JSON.stringify(props)}
      <HelloWorld {...props} />
    </div>
  </HelmetProvider>,
);

Issue: This duplicates the ReactHelmet component logic inline instead of using the component. This creates:

  • Code duplication (ReactHelmet already has the same structure)
  • Potential maintenance burden (two places to update)
  • Inconsistency with ReactHelmetAppBroken.server.jsx which correctly wraps <ReactHelmet />

Recommendation: Should be:

const componentHtml = renderToString(
  <HelmetProvider context={helmetContext}>
    <ReactHelmet {...props} />
  </HelmetProvider>,
);

2. Pro Package Parity Issue

The Pro dummy app (react_on_rails_pro/spec/dummy/package.json) still uses:

  • react-helmet: ^6.0.0-beta.2 (old package, should migrate to @dr.pogodin/react-helmet)
  • shakapacker: 9.3.0 (open source is now on 9.4.0)

Questions:

  • Should Pro also be updated to use @dr.pogodin/react-helmet for consistency?
  • Should Pro also bump shakapacker to 9.4.0?
  • Are there Pro-specific react-helmet usages that need similar updates?

Impact: Medium - Could cause confusion or test failures in Pro package


🔍 Testing Concerns

1. Integration Tests

The PR description shows unchecked test plan items:

  • Integration Tests pass
  • Lint passes
  • Manual test: Run spec/dummy app

Critical per CLAUDE.md:

NEVER claim a test is "fixed" without running it locally first

Recommendation: Before merging, confirm:

# Run integration tests locally
cd react_on_rails/spec/dummy
bundle exec rspec spec/system/integration_spec.rb

# Verify react-helmet rendering works
grep -A 10 'react-helmet' spec/system/integration_spec.rb

2. Redux Store Tests

Since redux-thunk import changed in 4 files, verify all Redux-related tests pass:

bundle exec rspec --tag redux

🔒 Security & Performance

Security: ✅ No Issues

  • Dependency updates are from trusted sources
  • @dr.pogodin/react-helmet is a well-maintained fork addressing React 19 compatibility
  • No new security vulnerabilities introduced

Performance: ✅ Neutral

  • React 19 should provide performance improvements
  • HelmetProvider context pattern is the standard approach (no perf concerns)

📋 Pre-Merge Checklist

Based on CLAUDE.md requirements:

  • Run linting locally: bundle exec rubocop (MANDATORY)
  • Verify trailing newlines: All files must end with newline
  • Test locally: Run bundle exec rspec to verify tests pass
  • Consider Pro package: Decide if Pro needs similar updates
  • Fix ReactHelmetApp.server.jsx: Use <ReactHelmet /> component instead of duplicating structure

📝 Minor Suggestions

  1. Gemfile.lock Shakapacker Update: The bump from 9.3.0 → 9.4.0 is included. Verify this doesn't introduce breaking changes.

  2. TypeScript Types Cleanup: Removed @types/react-helmet from devDependencies ✅ (correct, since new package likely has built-in types)


🎯 Summary

Overall Assessment: Good PR with one structural issue to address.

Required Changes:

  1. Fix ReactHelmetApp.server.jsx to use <ReactHelmet /> component
  2. Run local tests and update test plan checkboxes
  3. Consider Pro package parity

Recommended Changes:

  1. Update Pro dummy app to @dr.pogodin/react-helmet for consistency
  2. Document why Pro uses different shakapacker version if intentional

Approval Status: ⚠️ Conditional - Fix the component duplication issue, run tests locally, then this is good to merge.


Great work on the thorough dependency migration! The react-helmet → @dr.pogodin/react-helmet migration is especially important for React 19 compatibility. 🚀

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx (1)

8-32: Thunk update is correct; consider React 19 render API for this legacy entry

The move to import { thunk } from 'redux-thunk' and applyMiddleware(thunk) for store creation is consistent with the rest of the PR and the upgraded Redux stack. However, this entrypoint still uses ReactDOM.render/ReactDOM.hydrate, which are removed in React 19; if this “react16” example is actually executed against the React 19 dependency from spec/dummy/package.json, you may want to mirror the newer client entry’s createRoot/hydrateRoot pattern or clearly scope this bundle to a React 16 build.

Please double-check how this app-react16 bundle is built/loaded in your test matrix to ensure it doesn’t accidentally run against React 19’s removed ReactDOM.render API.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ba7b11b and 1026398.

⛔ Files ignored due to path filters (1)
  • react_on_rails/spec/dummy/Gemfile.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx (2 hunks)
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx (1 hunks)
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx (1 hunks)
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx (2 hunks)
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx (1 hunks)
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx (2 hunks)
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx (2 hunks)
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx (2 hunks)
  • react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx (2 hunks)
  • react_on_rails/spec/dummy/package.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS ensure files end with a newline character before committing/pushing

Files:

  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG*.md : Use changelog format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` (no hash in PR number)
📚 Learning: 2024-10-08T20:53:47.076Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-10-08T20:53:47.076Z
Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88.

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • react_on_rails/spec/dummy/package.json
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails/spec/dummy/package.json
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails/spec/dummy/package.json
📚 Learning: 2025-02-13T19:09:15.991Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/RSCWebpackLoader.ts:0-0
Timestamp: 2025-02-13T19:09:15.991Z
Learning: In React Server Components webpack loader, using `new Function('return import("react-server-dom-webpack/node-loader")')()` is necessary as a workaround to bypass TypeScript compilation issues with direct dynamic imports.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
📚 Learning: 2025-02-13T16:50:47.848Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/clientStartup.ts:18-21
Timestamp: 2025-02-13T16:50:47.848Z
Learning: In the react_on_rails module, the `reactOnRailsPageUnloaded` function in clientStartup.ts is intentionally kept private as it's only used internally as a callback for `onPageUnloaded`.

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
🧬 Code graph analysis (6)
react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx (3)
react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx (3)
  • store (32-32)
  • combinedReducer (27-27)
  • combinedProps (28-28)
react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx (3)
  • store (31-31)
  • combinedReducer (26-26)
  • combinedProps (27-27)
react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx (1)
  • combinedReducer (13-13)
react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx (2)
react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx (3)
  • store (37-37)
  • combinedReducer (32-32)
  • combinedProps (33-33)
react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx (1)
  • combinedReducer (13-13)
react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx (3)
react_on_rails/spec/dummy/client/app-react16/startup/ReduxApp.client.jsx (1)
  • combinedReducer (27-27)
react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx (1)
  • combinedReducer (32-32)
react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx (1)
  • combinedReducer (26-26)
react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx (2)
packages/react-on-rails/src/ReactDOMServer.cts (1)
  • renderToString (4-4)
react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx (1)
  • ReactHelmet (8-16)
react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx (1)
react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx (5)
  • helmetContext (21-21)
  • helmetContext (27-27)
  • componentHtml (22-26)
  • props (20-34)
  • renderedHtml (29-32)
react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx (1)
react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx (1)
  • props (10-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.4, 22, latest)
  • GitHub Check: build
  • GitHub Check: claude-review
🔇 Additional comments (12)
react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx (1)

2-7: Helmet import and provider expectations look good

Switching to @dr.pogodin/react-helmet and documenting that this component must be wrapped in a HelmetProvider aligns with the rest of the PR; no further changes needed here.

Please confirm your local build/SSR tests that exercise Helmet continue to pass with @dr.pogodin/react-helmet as configured in spec/dummy/package.json.

react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx (1)

9-31: Server Redux store now uses named thunk consistently

The switch to import { thunk } from 'redux-thunk' and applyMiddleware(thunk)(createStore)(...) keeps the server-side store in sync with the client and shared store setups.

Please rely on your server-rendering tests to confirm redux-thunk behavior is unchanged after the move to the named thunk export.

react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx (1)

2-15: Shared Redux store thunk wiring matches other entrypoints

Using the named thunk export in applyMiddleware(thunk)(createStore)(...) keeps the shared store aligned with the client/server Redux setups and the upgraded redux-thunk version.

Confirm any consumers of this shared store behave as before (especially async action flows) after the thunk import change.

react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.client.jsx (1)

3-14: Client ReactHelmet is correctly wrapped in HelmetProvider

Wrapping ReactHelmet in <HelmetProvider> on the client matches the expectations documented in ReactHelmet.jsx and the usage pattern for @dr.pogodin/react-helmet; the export signature remains compatible.

Please confirm client-side Helmet behavior (e.g., title updates) still works as expected when exercising this “broken” example in the dummy app.

react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx (1)

6-32: Server ‘broken’ Helmet example now follows HelmetProvider SSR pattern

Using HelmetProvider with a per-request helmetContext and deriving title from helmet.title.toString() matches the recommended SSR usage for @dr.pogodin/react-helmet, while preserving the intentionally “broken” single-argument signature described in the comments.

Please exercise the server-side dummy route that uses this startup file to confirm that both the intended error path (due to the non-generator signature) and the captured <title> still behave as expected under React 19.

react_on_rails/spec/dummy/client/app/startup/ReduxApp.client.jsx (1)

8-37: All redux-thunk imports consistently use named export pattern

Verification confirms the review comment is accurate:

  • All 4 files with redux-thunk imports use import { thunk } from 'redux-thunk' (named import)
  • No default imports remain
  • All store creation calls properly wire middleware: applyMiddleware(thunk)
  • File under review (lines 8 and 37) follows the same consistent pattern as other entrypoints
react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx (4)

19-21: LGTM! Thread-safe per-request context pattern.

The per-request helmetContext initialization correctly enables thread-safe helmet data capture for server-side rendering, consistent with the @dr.pogodin/react-helmet API pattern.


23-33: LGTM! Correct server-side rendering with HelmetProvider.

The rendering logic properly:

  • Wraps the component tree with HelmetProvider passing the per-request context
  • Uses inline Helmet to set the page title
  • Renders the HelloWorld component with forwarded props

This pattern aligns with the reference implementation in ReactHelmetAppBroken.server.jsx.


35-39: LGTM! Safe helmet data extraction.

The helmet extraction correctly:

  • Retrieves helmet data from the context after rendering
  • Includes a null check to prevent runtime errors
  • Converts helmet.title to string with a safe fallback

This matches the pattern in ReactHelmetAppBroken.server.jsx.


4-5: All imports are valid and correctly used.

The verification confirms:

  • HelloWorld.jsx exists at the expected path react_on_rails/spec/dummy/client/app/startup/HelloWorld.jsx
  • Helmet and HelmetProvider are correctly exported from @dr.pogodin/react-helmet per the library's API
  • The usage in the file is correct: HelmetProvider wraps components with an optional context object for SSR, and Helmet wraps head elements like <title>. This aligns exactly with the library's documentation
  • The file properly ends with a newline
react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.client.jsx (2)

3-3: Import aligns with client-side helmet usage pattern.

The HelmetProvider import from @dr.pogodin/react-helmet is correct for client-side rendering. Note: Library API verification requested in the server file review (ReactHelmetApp.server.jsx) applies here as well.


9-14: LGTM! Correct client-side HelmetProvider wrapper.

The client-side implementation correctly:

  • Wraps ReactHelmet with HelmetProvider (no context prop needed for client rendering)
  • Forwards props to the wrapped component
  • Matches the pattern in ReactHelmetAppBroken.client.jsx

This completes the client-side migration to @dr.pogodin/react-helmet.

Comment on lines 21 to 28
"@dr.pogodin/react-helmet": "^3.0.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-on-rails": "link:.yalc/react-on-rails",
"react-redux": "^8.0.2",
"react-redux": "^9.2.0",
"react-router-dom": "^6.0.0",
"redux": "^4.0.1",
"redux-thunk": "^2.2.0",
"redux": "^5.0.1",
"redux-thunk": "^3.1.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Script executed:

#!/bin/bash
# Find all package.json files in the repository
fd package.json -t f

Repository: shakacode/react_on_rails


<shell_result>
Repository: shakacode/react_on_rails
Exit code: 0

stdout:

package.json
packages/react-on-rails/package.json
packages/react-on-rails-pro/package.json
packages/react-on-rails-pro-node-renderer/package.json
react_on_rails/spec/dummy/package.json
react_on_rails/spec/react_on_rails/fixtures/absolute_path_package.json
react_on_rails/spec/react_on_rails/fixtures/beta_package.json
react_on_rails/spec/react_on_rails/fixtures/git_package.json
react_on_rails/spec/react_on_rails/fixtures/normal_package.json
react_on_rails/spec/react_on_rails/fixtures/pro_package.json
react_on_rails/spec/react_on_rails/fixtures/pro_semver_caret_package.json
react_on_rails/spec/react_on_rails/fixtures/relative_path_package.json
react_on_rails/spec/react_on_rails/fixtures/semver_caret_package.json
react_on_rails/spec/react_on_rails/fixtures/semver_exact_package.json
react_on_rails/spec/react_on_rails/fixtures/semver_range_package.json
react_on_rails/spec/react_on_rails/fixtures/semver_tilde_package.json
react_on_rails/spec/react_on_rails/fixtures/similar_packages_package.json
react_on_rails/spec/react_on_rails/fixtures/yalc_package.json
react_on_rails_pro/package.json
react_on_rails_pro/spec/dummy/package.json
react_on_rails_pro/spec/execjs-compatible-dummy/package.json

</shell_result>


Script executed:

#!/bin/bash
# Extract React/Redux/Helmet versions from key package.json files
echo "=== Root package.json ==="
cat package.json | jq '.dependencies // empty | {react: .react, "react-dom": .["react-dom"], "react-redux": .["react-redux"], redux: .redux, "redux-thunk": .["redux-thunk"], "@dr.pogodin/react-helmet": .["@dr.pogodin/react-helmet"]} | del(.[] | select(. == null))' 2>/dev/null || echo "No dependencies section"

echo -e "\n=== packages/react-on-rails/package.json ==="
cat packages/react-on-rails/package.json | jq '.peerDependencies // empty | {react: .react, "react-dom": .["react-dom"], "react-redux": .["react-redux"], redux: .redux, "redux-thunk": .["redux-thunk"], "@dr.pogodin/react-helmet": .["@dr.pogodin/react-helmet"]} | del(.[] | select(. == null))' 2>/dev/null || echo "No peerDependencies section"

echo -e "\n=== react_on_rails/spec/dummy/package.json ==="
cat react_on_rails/spec/dummy/package.json | jq '.dependencies // empty | {react: .react, "react-dom": .["react-dom"], "react-redux": .["react-redux"], redux: .redux, "redux-thunk": .["redux-thunk"], "@dr.pogodin/react-helmet": .["@dr.pogodin/react-helmet"]} | del(.[] | select(. == null))' 2>/dev/null || echo "No dependencies section"

echo -e "\n=== react_on_rails_pro/package.json ==="
cat react_on_rails_pro/package.json | jq '.dependencies // empty | {react: .react, "react-dom": .["react-dom"], "react-redux": .["react-redux"], redux: .redux, "redux-thunk": .["redux-thunk"], "@dr.pogodin/react-helmet": .["@dr.pogodin/react-helmet"]} | del(.[] | select(. == null))' 2>/dev/null || echo "No dependencies section"

echo -e "\n=== react_on_rails_pro/spec/dummy/package.json ==="
cat react_on_rails_pro/spec/dummy/package.json | jq '.dependencies // empty | {react: .react, "react-dom": .["react-dom"], "react-redux": .["react-redux"], redux: .redux, "redux-thunk": .["redux-thunk"], "@dr.pogodin/react-helmet": .["@dr.pogodin/react-helmet"]} | del(.[] | select(. == null))' 2>/dev/null || echo "No dependencies section"

Repository: shakacode/react_on_rails


<shell_result>
Repository: shakacode/react_on_rails
Exit code: 0

stdout:

=== Root package.json ===

=== packages/react-on-rails/package.json ===
{
  "react": ">= 16",
  "react-dom": ">= 16"
}

=== react_on_rails/spec/dummy/package.json ===
{
  "react": "^19.0.0",
  "react-dom": "^19.0.0",
  "react-redux": "^9.2.0",
  "redux": "^5.0.1",
  "redux-thunk": "^3.1.0",
  "@dr.pogodin/react-helmet": "^3.0.4"
}

=== react_on_rails_pro/package.json ===

=== react_on_rails_pro/spec/dummy/package.json ===
{
  "react": "19.0.0",
  "react-dom": "19.0.0",
  "react-redux": "^9.2.0",
  "redux": "^5.0.1",
  "redux-thunk": "^3.1.0"
}

</shell_result>


Script executed:

#!/bin/bash
# Check if CHANGELOG.md was updated
echo "=== Recent CHANGELOG.md entries ==="
head -50 CHANGELOG.md

echo -e "\n=== Check git diff for CHANGELOG.md ==="
git diff HEAD~1 CHANGELOG.md 2>/dev/null | head -30 || echo "Cannot get git diff"

Repository: shakacode/react_on_rails


<shell_result>
Repository: shakacode/react_on_rails
Exit code: 0

stdout:

=== Recent CHANGELOG.md entries ===
# Change Log

All notable changes to this project's source code will be documented in this file. Items under `Unreleased` is upcoming features that will be out in the next version.

Migration instructions for the major updates can be found [here](https://www.shakacode.com/react-on-rails/docs/guides/upgrading-react-on-rails#upgrading-to-version-9.md). Some smaller migration information can be found here.

## Want to Save Time Updating?

If you need help upgrading `react_on_rails`, `webpacker` to `shakapacker`, or JS packages, contact [email protected]. We can upgrade your project and improve your development and customer experiences, allowing you to focus on building new features or fixing bugs instead.

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/).

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:[email protected]), the creator of React on Rails and Shakapacker.

## Contributors

Please follow the recommendations outlined at [keepachangelog.com](http://keepachangelog.com/). Please use the existing headings and styling as a guide.
After a release, please make sure to run `bundle exec rake update_changelog`. This will add a heading for the latest version and update the links at the end of the file.

## Versions

### [Unreleased]

Changes since the last non-beta release.

#### Added

- **Service Dependency Checking for bin/dev**: Added optional `.dev-services.yml` configuration to validate required external services (Redis, PostgreSQL, Elasticsearch, etc.) are running before `bin/dev` starts the development server. Provides clear error messages with start commands and install hints when services are missing. Zero impact if not configured - backwards compatible with all existing installations. [PR 2098](https://github.com/shakacode/react_on_rails/pull/2098) by [justin808](https://github.com/justin808).

#### Changed

- **Monorepo Structure Reorganization**: Restructured the monorepo to use two top-level product directories (`react_on_rails/` and `react_on_rails_pro/`) instead of mixing source files at the root level. This improves organization and clarity for contributors working on either the open-source or Pro versions. **Important for contributors**: If you have an existing clone of the repository, you may need to update your IDE exclusion patterns and paths. See the updated `CLAUDE.md` for current project structure. [PR 2114](https://github.com/shakacode/react_on_rails/pull/2114) by [justin808](https://github.com/justin808).

- **Package Manager Migration to pnpm (Contributors Only)**: Migrated the monorepo from Yarn Classic to pnpm for improved dependency management and faster installs. **This only affects contributors** - end users can continue using any package manager (npm, yarn, pnpm) with their applications. Contributors should reinstall dependencies with `pnpm install` after pulling this change. [PR 2121](https://github.com/shakacode/react_on_rails/pull/2121) by [justin808](https://github.com/justin808).

#### Improved

- **Automatic Precompile Hook Coordination in bin/dev**: The `bin/dev` command now automatically runs Shakapacker's `precompile_hook` once before starting development processes and sets `SHAKAPACKER_SKIP_PRECOMPILE_HOOK=true` to prevent duplicate execution in spawned webpack processes.
  - Eliminates the need for manual coordination, sleep hacks, and duplicate task calls in Procfile.dev
  - Users can configure expensive build tasks (like locale generation or ReScript compilation) once in `config/shakapacker.yml` and `bin/dev` handles coordination automatically
  - Includes warning for Shakapacker versions below 9.4.0 (the `SHAKAPACKER_SKIP_PRECOMPILE_HOOK` environment variable is only supported in 9.4.0+)
  - The `SHAKAPACKER_SKIP_PRECOMPILE_HOOK` environment variable is set for all spawned processes, making it available for custom scripts that need to detect when `bin/dev` is managing the precompile hook
  - Addresses [2091](https://github.com/shakacode/react_on_rails/issues/2091) by [justin808](https://github.com/justin808)

- **Idempotent Locale Generation**: The `react_on_rails:locale` rake task is now idempotent, automatically skipping generation when locale files are already up-to-date. This makes it safe to call multiple times (e.g., in Shakapacker's `precompile_hook`) without duplicate work. Added `force=true` option to override timestamp checking. [PR 2090](https://github.com/shakacode/react_on_rails/pull/2090) by [justin808](https://github.com/justin808).

### [v16.2.0.beta.12] - 2025-11-20

#### Added


=== Check git diff for CHANGELOG.md ===

</shell_result>


Script executed:

#!/bin/bash
# Check lines 35-45 in spec/dummy/package.json to see the devDependencies
sed -n '35,45p' react_on_rails/spec/dummy/package.json

Repository: shakacode/react_on_rails


<shell_result>
Repository: shakacode/react_on_rails
Exit code: 0

stdout:

    "@babel/preset-react": "^7.10.4",
    "@playwright/test": "^1.55.1",
    "@pmmmwh/react-refresh-webpack-plugin": "^0.5.1",
    "@rescript/react": "^0.13.0",
    "@types/react": "^19.0.0",
    "@types/react-dom": "^19.0.0",
    "babel-loader": "8.2.4",
    "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
    "compression-webpack-plugin": "9",
    "css-loader": "^6.5.1",
    "expose-loader": "^1.0.3",

</shell_result>


Based on my verification, I've identified real cross-package inconsistencies and a missing CHANGELOG entry. Here's the rewritten review comment:


Version inconsistencies exist across spec/dummy packages; React 19 upgrade missing from CHANGELOG

Cross-package comparison reveals:

  • react_on_rails/spec/dummy/package.json: React ^19.0.0, React-Redux ^9.2.0, Redux ^5.0.1, redux-thunk ^3.1.0, @dr.pogodin/react-helmet ^3.0.4
  • react_on_rails_pro/spec/dummy/package.json: React 19.0.0 (exact version, not caret), React-Redux ^9.2.0, Redux ^5.0.1, redux-thunk ^3.1.0, @dr.pogodin/react-helmet missing

The semver mismatch (^19.0.0 vs 19.0.0) and missing Helmet dependency between the two spec/dummy packages should be reconciled. Additionally, per project guidelines, the React 19 upgrade and dependency bumps should be documented in CHANGELOG.md under the Unreleased section.

🤖 Prompt for AI Agents
In react_on_rails/spec/dummy/package.json around lines 21-28 there is a
semver/dep mismatch vs react_on_rails_pro/spec/dummy/package.json (this file
uses "react": "^19.0.0" and includes "@dr.pogodin/react-helmet": "^3.0.4", while
the pro package uses "react": "19.0.0" and omits Helmet); make the versions
consistent across both spec/dummy package.json files (choose careted or exact
for react and apply the same style to react-dom), add the missing
@dr.pogodin/react-helmet dependency to
react_on_rails_pro/spec/dummy/package.json with the same version, and add a
brief entry under the Unreleased section of CHANGELOG.md documenting the React
19 upgrade and dependency bumps.

@justin808
Copy link
Member Author

/run-skipped-ci

@github-actions
Copy link
Contributor

🚀 Full CI Mode Enabled

Triggered all workflows for full CI coverage

Note: Added the full-ci label to this PR. All future commits will run the full CI suite (including minimum dependency tests) until the label is removed.

To disable full CI mode, use the /stop-run-skipped-ci command.

View progress in the Actions tab.

…ct-helmet

Changes:
- Fix ReactHelmetApp.server.jsx to wrap ReactHelmet component instead of
  duplicating component logic inline
- Migrate react_on_rails_pro/spec/dummy to @dr.pogodin/react-helmet (React 19 compatible)
- Update Pro shakapacker from 9.3.0 to 9.4.0 for consistency with open source
- Add HelmetProvider wrappers to all client and server entry points in Pro
- Use exact React 19.0.0 versions (consistent between open source and Pro)
- Rename loadable-client.imports-loadable.js to .jsx (now contains JSX)

The @dr.pogodin/react-helmet migration replaces Helmet.renderStatic() with
the thread-safe HelmetProvider context pattern for SSR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Nov 26, 2025

Code Review: React 19 Compatibility Update

I've reviewed this PR for upgrading the spec/dummy apps to React 19 compatibility. Overall, this is a well-executed migration with appropriate dependency updates and code changes. Here's my detailed feedback:


✅ Strengths

1. Comprehensive Dependency Updates

The dependency upgrade path is correct and well-documented:

  • React 18 → 19 (latest major version)
  • react-redux 8.x → 9.2.0 (React 19 compatible)
  • redux 4.x → 5.0.1 (required by react-redux 9.x)
  • redux-thunk 2.x → 3.1.0 (required by redux 5.x)
  • Migrated to @dr.pogodin/react-helmet (thread-safe React 19 fork)

2. Correct redux-thunk Migration

The change from default export to named export is correct:

// ✅ Correct migration
import { thunk } from 'redux-thunk';  // v3.x uses named export
applyMiddleware(thunk)

All instances properly updated in:

  • SharedReduxStore.jsx:27
  • ReduxApp.client.jsx:37
  • ReduxApp.server.jsx:28

3. Thread-Safe react-helmet Implementation

The SSR implementation correctly uses HelmetProvider with context object for thread-safety:

const helmetContext = {};
const componentHtml = renderToString(
  <HelmetProvider context={helmetContext}>
    {/* ... */}
  </HelmetProvider>
);
const { helmet } = helmetContext;

This is critical for preventing data leakage between concurrent server-side requests.

4. Good Documentation

  • Inline comments explain why HelmetProvider is required
  • PR description clearly documents all changes
  • Migration path is traceable

⚠️ Issues & Concerns

1. CRITICAL: Inconsistent ReactHelmetApp.server.jsx Implementation

Location: react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx:19-41

The refactored server component completely removes the original ReactHelmet component and replaces it with an inline version:

// ❌ BEFORE: Used ReactHelmet component
import ReactHelmet from '../components/ReactHelmet';
const componentHtml = renderToString(<ReactHelmet {...props} />);

// ⚠️ AFTER: Inline implementation bypasses ReactHelmet component
import HelloWorld from './HelloWorld';
const componentHtml = renderToString(
  <HelmetProvider context={helmetContext}>
    <div>
      <Helmet>
        <title>Custom page title</title>
      </Helmet>
      Props: {JSON.stringify(props)}
      <HelloWorld {...props} />
    </div>
  </HelmetProvider>
);

Problems:

  1. Changes behavior: The component no longer uses ReactHelmet, which may have different props/logic
  2. Inconsistency: Client version (ReactHelmetApp.client.jsx:10-14) still uses <ReactHelmet {...props} />, but server version doesn't
  3. Test coverage: If integration tests expect specific ReactHelmet behavior, they may now pass for wrong reasons
  4. Maintenance risk: Future changes to ReactHelmet component won't affect SSR path

Recommendation:

// ✅ Correct approach: Wrap existing component, don't replace it
import ReactHelmet from '../components/ReactHelmet';

export default (props, _railsContext) => {
  const helmetContext = {};
  const componentHtml = renderToString(
    <HelmetProvider context={helmetContext}>
      <ReactHelmet {...props} />
    </HelmetProvider>,
  );
  const { helmet } = helmetContext;

  return {
    renderedHtml: {
      componentHtml,
      title: helmet ? helmet.title.toString() : '',
    },
  };
};

This matches the pattern used in ReactHelmetAppBroken.server.jsx:21-27.


2. Defensive Null Checks May Hide Issues

Location: All server files with helmet ? helmet.title.toString() : ''

While defensive programming is good, returning empty strings when helmet is undefined may hide bugs:

title: helmet ? helmet.title.toString() : '',  // Silently fails

Concern: If HelmetProvider isn't working correctly, this will fail silently instead of throwing an error that would alert developers.

Recommendation: Consider logging warnings or throwing descriptive errors in development:

if (!helmet && process.env.NODE_ENV === 'development') {
  console.warn('HelmetProvider context is empty. Check HelmetProvider setup.');
}
title: helmet?.title.toString() ?? '',

3. Missing Test Coverage Documentation

The PR description has unchecked test plan items:

- [ ] Integration Tests pass
- [ ] Lint passes
- [ ] Manual test: Run spec/dummy app

Questions:

  1. Have you verified that spec/dummy/spec/system/integration_spec.rb:288 still passes? (It checks for "RENDERED ReactHelmetApp")
  2. Have you manually tested both client and server rendering of ReactHelmet components?
  3. Have you tested the Pro dummy app's loadable components with Helmet?

Per CLAUDE.md CRITICAL REQUIREMENTS:

"NEVER claim a test is 'fixed' without running it locally first"
"Distinguish hypothetical fixes from confirmed fixes"

Please update the PR description with actual test results, or clearly state if testing was done in an environment with limitations.


4. File Extension Changes (.js → .jsx)

Location: react_on_rails_pro/spec/dummy/client/app/loadable/

Files renamed from .js to .jsx:

  • loadable-client.imports-loadable.jsloadable-client.imports-loadable.jsx
  • loadable-server.imports-hmr.jsx (already .jsx)
  • loadable-server.imports-loadable.jsx (already .jsx)

Observation: This is a good practice (JSX in .jsx files), but verify:

  1. Are all import paths updated? (Check if anything imports these files by old names)
  2. Do any webpack configurations rely on specific file extensions?
# Recommended verification:
grep -r "loadable-client.imports-loadable.js" react_on_rails_pro/ --exclude-dir=node_modules

The ERB file update (loadable_component.html.erb:26) shows awareness of this change, which is good.


🔍 Additional Observations

5. Shakapacker Version Bump

Both dummy apps upgraded shakapacker from 9.3.0 → 9.4.0:

  • react_on_rails/spec/dummy/Gemfile.lock:348,464
  • react_on_rails_pro/spec/dummy/package.json:66

Question: Is this intentional or a side-effect of dependency resolution? The PR description doesn't mention this upgrade. Check the Shakapacker 9.4.0 changelog for any breaking changes or relevant updates.


6. Documentation Update in Pro

The code-splitting-loadable-components.md file received formatting improvements (line breaks, link corrections). These are good housekeeping changes.


🧪 Testing Recommendations

Per CLAUDE.md guidelines, you should run these before merging:

# 1. Verify no RuboCop violations
bundle exec rubocop

# 2. Test the specific integration
cd react_on_rails/spec/dummy
bundle exec rspec spec/system/integration_spec.rb -e "ReactHelmet"

# 3. Run full dummy app specs
cd react_on_rails/spec/dummy
rake run_rspec:dummy

# 4. Test Pro dummy app
cd react_on_rails_pro/spec/dummy
rake run_rspec:dummy

# 5. Verify builds succeed
cd react_on_rails/spec/dummy
pnpm run build:test

# 6. Check for any runtime console errors when loading pages with Helmet

📋 Security & Performance

Security ✅

  • Thread-safety: HelmetProvider with per-request context prevents data leakage
  • No new XSS vectors: All changes are within controlled rendering
  • Dependencies: Using maintained fork (@dr.pogodin/react-helmet) with active security updates

Performance ✅

  • No regressions expected: Redux 5.x and react-redux 9.x have similar performance characteristics
  • SSR overhead: HelmetProvider adds minimal overhead (context object creation)

🎯 Recommendations Summary

Must Fix Before Merge:

  1. Fix ReactHelmetApp.server.jsx to use the ReactHelmet component instead of inline implementation (consistency issue)
  2. Document actual test results in PR description (per CLAUDE.md requirements)

Should Consider:

  1. Add development warnings when helmet is undefined
  2. Verify Shakapacker 9.4.0 upgrade is intentional and compatible
  3. Ensure all file path references are updated for .js → .jsx renames

Nice to Have:

  1. Add inline comments explaining why both client and server need HelmetProvider
  2. Consider adding a test that specifically validates helmet SSR output

📊 Overall Assessment

Quality: 🟡 Good with one critical fix needed
Risk: 🟢 Low (well-isolated to test apps)
Completeness: 🟡 Missing test verification documentation

This is a solid upgrade path to React 19. The main concern is the ReactHelmetApp.server.jsx refactoring that changes component behavior. Once that's addressed and tests are confirmed passing, this should be ready to merge.

Great work on maintaining backward compatibility patterns and providing clear documentation! 🚀

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
react_on_rails_pro/docs/code-splitting-loadable-components.md (1)

24-24: Use hyphenated compound adjectives for "Server-side Rendering".

Lines 24 and 90 use "Server Side Rendering" as a compound adjective modifying a noun. Hyphenate compound adjectives for proper English grammar: "Server-side Rendering".

-[`@loadable/babel-plugin`](https://loadable-components.com/docs/getting-started/) - The plugin transforms your code to be ready for Server Side Rendering.
+[`@loadable/babel-plugin`](https://loadable-components.com/docs/getting-started/) - The plugin transforms your code to be ready for Server-side Rendering.

Also applies to: 90-90

react_on_rails_pro/spec/dummy/package.json (1)

53-66: Pro dummy deps now match OSS dummy; consider aligning TS React types as a follow-up

Adding @dr.pogodin/react-helmet and pinning shakapacker to 9.4.0 brings this dummy in line with the main react_on_rails/spec/dummy/package.json for the React 19 + Helmet stack, which addresses the earlier cross-package mismatch.

One remaining nit: the OSS dummy has React 19-compatible type packages, while this pro dummy still lists @types/react-dom at ^18.x. Not urgent for a sample app, but it’s worth aligning TS React/DOM types between the two dummies to avoid confusing version skew for contributors.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1026398 and 05b231e.

📒 Files selected for processing (15)
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx (2 hunks)
  • react_on_rails/spec/dummy/package.json (1 hunks)
  • react_on_rails_pro/docs/code-splitting-loadable-components.md (15 hunks)
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx (2 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx (1 hunks)
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx (2 hunks)
  • react_on_rails_pro/spec/dummy/package.json (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS ensure files end with a newline character before committing/pushing

Files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
🧠 Learnings (20)
📓 Common learnings
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG*.md : Use changelog format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` (no hash in PR number)
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG.md : Update `/CHANGELOG.md` for user-visible changes (features, bug fixes, breaking changes, deprecations, performance improvements) to the open-source React on Rails gem and npm package

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
Repo: shakacode/react_on_rails PR: 1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-01-23T18:20:45.824Z
Learnt from: alexeyr-ci
Repo: shakacode/react_on_rails PR: 1687
File: spec/dummy/package.json:0-0
Timestamp: 2025-01-23T18:20:45.824Z
Learning: When adding or updating dependencies in spec/dummy/package.json, maintain version consistency with other package.json files in the codebase to avoid potential version conflicts.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/package.json
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
Repo: shakacode/react_on_rails PR: 1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-02-12T16:38:06.537Z
Learnt from: Romex91
Repo: shakacode/react_on_rails PR: 1697
File: package-scripts.yml:28-28
Timestamp: 2025-02-12T16:38:06.537Z
Learning: The file `node_package/lib/ReactOnRails.full.js` is autogenerated during the build process and should not be present in the repository.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG*.md : Use changelog format: `[PR 1818](https://github.com/shakacode/react_on_rails/pull/1818) by [username](https://github.com/username)` (no hash in PR number)

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: The `react_on_rails_pro/` directory has its own Prettier/ESLint configuration and must be linted separately

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-10-23T17:22:01.074Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1875
File: lib/react_on_rails/utils.rb:112-124
Timestamp: 2025-10-23T17:22:01.074Z
Learning: In React on Rails, when Pro is installed but not licensed, the intended behavior is to raise an error on boot. The `react_on_rails_pro?` method validates licenses and should raise errors early (including during path resolution in methods like `server_bundle?`) to enforce licensing requirements rather than failing later with obscure errors.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to /CHANGELOG_PRO.md : Update `/CHANGELOG_PRO.md` for Pro-only features, fixes, and changes affecting Pro packages

Applied to files:

  • react_on_rails/spec/dummy/package.json
📚 Learning: 2025-02-13T19:09:15.991Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/RSCWebpackLoader.ts:0-0
Timestamp: 2025-02-13T19:09:15.991Z
Learning: In React Server Components webpack loader, using `new Function('return import("react-server-dom-webpack/node-loader")')()` is necessary as a workaround to bypass TypeScript compilation issues with direct dynamic imports.

Applied to files:

  • react_on_rails/spec/dummy/package.json
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-02-13T16:50:47.848Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/clientStartup.ts:18-21
Timestamp: 2025-02-13T16:50:47.848Z
Learning: In the react_on_rails module, the `reactOnRailsPageUnloaded` function in clientStartup.ts is intentionally kept private as it's only used internally as a callback for `onPageUnloaded`.

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2024-07-27T10:08:35.868Z
Learnt from: theforestvn88
Repo: shakacode/react_on_rails PR: 1620
File: spec/dummy/client/app/startup/HelloTurboStream.jsx:3-3
Timestamp: 2024-07-27T10:08:35.868Z
Learning: The `RailsContext` import in `spec/dummy/client/app/startup/HelloTurboStream.jsx` is used later in the project, as clarified by the user theforestvn88.

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx
  • react_on_rails_pro/spec/dummy/package.json
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx
  • react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb
  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to lib/react_on_rails/*.rb : Create RBS signature files for new Ruby files in `lib/react_on_rails/` by adding corresponding `.rbs` file in `sig/react_on_rails/`, adding to Steepfile, and validating before committing

Applied to files:

  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-11-25T08:05:17.804Z
Learnt from: CR
Repo: shakacode/react_on_rails PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T08:05:17.804Z
Learning: Applies to sig/react_on_rails/**/*.rbs : In RBS type signature files, define type signatures that correspond to Ruby files in `lib/react_on_rails/`

Applied to files:

  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-04-09T12:56:10.756Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1696
File: node_package/src/RSCPayloadContainer.ts:0-0
Timestamp: 2025-04-09T12:56:10.756Z
Learning: In the react_on_rails codebase, RSC payloads are already stringified using `JSON.stringify()` before being processed by the `escapeScript` function, which handles escaping of special characters. The function only needs to handle specific HTML markers like comments and closing script tags.

Applied to files:

  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • react_on_rails_pro/docs/code-splitting-loadable-components.md
📚 Learning: 2025-02-13T16:50:26.861Z
Learnt from: AbanoubGhadban
Repo: shakacode/react_on_rails PR: 1644
File: node_package/src/turbolinksUtils.ts:34-36
Timestamp: 2025-02-13T16:50:26.861Z
Learning: In React on Rails, when checking for Turbolinks version 5 using `turbolinksVersion5()`, always ensure `Turbolinks` exists first by checking `turbolinksInstalled()` to prevent TypeError when accessing properties.

Applied to files:

  • react_on_rails_pro/docs/code-splitting-loadable-components.md
🧬 Code graph analysis (5)
react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx (7)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx (3)
  • helmetContext (11-11)
  • helmetContext (17-17)
  • componentHtml (12-16)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx (3)
  • helmetContext (19-19)
  • helmetContext (27-27)
  • componentHtml (20-26)
react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx (1)
  • ReactHelmet (6-19)
react_on_rails/spec/dummy/client/app/components/ReactHelmet.jsx (1)
  • ReactHelmet (8-16)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx (1)
  • props (11-15)
react_on_rails/spec/dummy/client/app/startup/ReduxApp.server.jsx (1)
  • props (22-40)
react_on_rails/spec/dummy/client/app/stores/SharedReduxStore.jsx (1)
  • props (10-16)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx (1)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx (3)
  • helmetContext (11-11)
  • helmetContext (17-17)
  • componentHtml (12-16)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx (1)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx (4)
  • railsContext (16-16)
  • helmetContext (19-19)
  • helmetContext (27-27)
  • componentHtml (20-26)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx (4)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx (1)
  • props (11-15)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx (1)
  • props (19-46)
react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx (1)
  • railsContext (16-16)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ApolloGraphQLApp.client.jsx (1)
  • el (24-24)
react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx (1)
react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx (1)
  • ReactHelmet (6-19)
🪛 LanguageTool
react_on_rails_pro/docs/code-splitting-loadable-components.md

[uncategorized] ~24-~24: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...in transforms your code to be ready for Server Side Rendering. - @loadable/component - Ma...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[uncategorized] ~68-~68: “React” is a proper noun and needs to be capitalized.
Context: ...unkCountPlugin({ maxChunks: 1 })` The react_on_rails_pro node-renderer expects only...

(A_GOOGLE)


[uncategorized] ~90-~90: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...in transforms your code to be ready for Server Side Rendering Add this to `babel.config.js...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🪛 markdownlint-cli2 (0.18.1)
react_on_rails_pro/docs/code-splitting-loadable-components.md

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


100-100: Bare URL used

(MD034, no-bare-urls)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20, minimum)
  • GitHub Check: examples (3.4, latest)
  • GitHub Check: examples (3.2, minimum)
  • GitHub Check: pro-lint-js-and-ruby
  • GitHub Check: build
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: claude-review
🔇 Additional comments (19)
react_on_rails_pro/spec/dummy/app/views/pages/pro/loadable_component.html.erb (1)

26-26: Client code snippet path update to .jsx looks correct

Using the .jsx client imports file here matches the server snippet above and the JSX language hint, so this change keeps the docs in sync with the actual JSX-based client startup. No issues from this change.

react_on_rails_pro/docs/code-splitting-loadable-components.md (1)

1-100: File already ends with a newline character—no action required.

The verification confirms that react_on_rails_pro/docs/code-splitting-loadable-components.md already complies with the coding guideline requiring all files to end with a newline character. The file is in the correct state.

react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-loadable.jsx (2)

5-5: HelmetProvider import matches new Helmet fork usage

Importing HelmetProvider from @dr.pogodin/react-helmet is consistent with the rest of the dummy app’s migration and is the right entry for the forked, React‑19‑compatible Helmet implementation. No issues here; just ensure the dependency is installed and resolved in this package.json scope.


12-17: Hydration wrapper with HelmetProvider looks correct and consistent

Wrapping the hydrated ClientApp with <HelmetProvider> preserves the existing props (including path: railsContext.pathname) while enabling Helmet context during hydration. This matches the HelmetProvider pattern used in the ReactHelmet* client/server files and should keep head management consistent for loadable routes.

react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx (5)

7-7: LGTM! Correct import for the new helmet package.

The import correctly references the thread-safe React 19-compatible fork mentioned in the PR objectives.


17-26: LGTM! Correct implementation of thread-safe SSR pattern.

The per-request helmetContext and HelmetProvider wrapper correctly implement the thread-safe server-side rendering pattern for the new helmet package, while preserving the existing loadable chunks collection behavior.


27-27: LGTM! Correct extraction of helmet data.

The destructuring correctly retrieves the helmet data populated by HelmetProvider during rendering.


43-43: File already complies with newline requirement.

The file react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx ends with a newline character as required by coding guidelines. No action needed.


32-38: Based on my comprehensive verification of the codebase, I can now provide the rewritten review comment:


Code does not require API verification—helmet property access is used consistently and correctly throughout the codebase.

The guarded property access pattern (helmet ? helmet.link.toString() : '', etc.) matches the pattern used across all server-side rendering files in the project (react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx, react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx, and react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx). The @dr.pogodin/react-helmet dependency (version ^3.0.4) is active and functioning correctly. The file correctly ends with a newline character.

react_on_rails_pro/spec/dummy/client/app/loadable/loadable-client.imports-hmr.jsx (1)

2-10: Client HMR wrapper correctly upgraded to use HelmetProvider

The generator signature stays intact and wrapping Loadable with HelmetProvider (without a context object) is the expected client-side usage with @dr.pogodin/react-helmet. No issues from a React on Rails integration standpoint.

react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx (1)

3-25: SSR HMR integration with HelmetProvider and helmetContext looks correct

The HMR server entry now follows the standard pattern for @dr.pogodin/react-helmet SSR: per-request helmetContext, HelmetProvider context={helmetContext} during renderToString, and safe extraction of helmet fields (link/meta/style/title) with empty-string fallbacks. This keeps the existing API shape while making the SSR path thread-safe.

react_on_rails/spec/dummy/package.json (1)

21-28: React 19 + Redux 5 + Helmet stack in the dummy app is consistent and appropriate

The dummy app now cleanly targets React 19 with matching React DOM, updated react-redux/redux/redux-thunk, and @dr.pogodin/react-helmet. These versions align with the pro dummy and provide a coherent React 19 test surface without tightening the library’s published peerDeps.

react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx (1)

4-34: Server-side ReactHelmet now uses the per-request HelmetProvider pattern

Using HelmetProvider with a fresh helmetContext per call and deriving title from helmetContext.helmet matches the recommended SSR integration for @dr.pogodin/react-helmet, while preserving the existing { renderedHtml } contract. Keeping this example focused on title is fine given the more detailed loadable/HMR demos elsewhere.

react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/A.jsx (1)

2-2: Page A correctly switched to @dr.pogodin/react-helmet

Only the import source changed; the Helmet usage remains the same and will now participate in the HelmetProvider context provided by the Loadable wrappers.

react_on_rails_pro/spec/dummy/client/app/components/Loadable/pages/B.jsx (1)

2-2: Page B Helmet import migrated consistently

The component now pulls Helmet from @dr.pogodin/react-helmet, matching Page A and the rest of the React 19-compatible stack, with no behavioral changes.

react_on_rails_pro/spec/dummy/client/app/components/ReactHelmet.jsx (1)

2-2: Pro ReactHelmet component now aligned with the new Helmet package

Switching the import to @dr.pogodin/react-helmet keeps the component logic intact and matches the HelmetProvider-based client/server startup code introduced elsewhere in the dummy app.

react_on_rails_pro/spec/dummy/client/app/components/Loadable/Header.jsx (1)

2-2: LGTM! Clean migration to React 19-compatible helmet library.

The import change from react-helmet to @dr.pogodin/react-helmet is correct. The Helmet component API remains unchanged, making this a seamless upgrade.

react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.client.jsx (1)

5-14: LGTM! Correct HelmetProvider integration for client-side rendering.

The addition of HelmetProvider wrapper follows the documented pattern for @dr.pogodin/react-helmet. The comment on line 10 clearly explains the requirement, and the implementation matches the patterns used in other client-side files across the PR.

react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx (1)

8-8: LGTM! Thread-safe server-side helmet implementation.

The migration to HelmetProvider with per-request helmetContext follows the correct pattern for @dr.pogodin/react-helmet on the server. This approach ensures thread-safety by capturing helmet data per request rather than using the previous Helmet.renderStatic() method. The defensive check on line 43 (helmet ? helmet.title.toString() : '') properly handles cases where helmet may be undefined.

Also applies to: 31-43

by ShakaCode

*Last updated September 19, 2022*
_Last updated September 19, 2022_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Replace emphasis formatting with plain text for the date line.

Line 5 uses emphasis (_..._) for metadata, which violates MD036 (no-emphasis-as-heading). Metadata like dates should be plain text or a formal heading if needed.

-_Last updated September 19, 2022_
+Last updated September 19, 2022
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_Last updated September 19, 2022_
Last updated September 19, 2022
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

5-5: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🤖 Prompt for AI Agents
In react_on_rails_pro/docs/code-splitting-loadable-components.md around line 5,
the date line uses emphasis markdown `_Last updated September 19, 2022_` which
triggers MD036; remove the surrounding underscores and make it plain text (e.g.,
Last updated September 19, 2022) or convert it to a proper heading if a heading
is desired.

```
https://loadable-components.com/docs/babel-plugin/

https://loadable-components.com/docs/babel-plugin/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Wrap bare URL in markdown link syntax.

Line 100 contains a bare URL that should be wrapped in proper markdown link format per MD034.

-https://loadable-components.com/docs/babel-plugin/
+[https://loadable-components.com/docs/babel-plugin/](https://loadable-components.com/docs/babel-plugin/)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
https://loadable-components.com/docs/babel-plugin/
[https://loadable-components.com/docs/babel-plugin/](https://loadable-components.com/docs/babel-plugin/)
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

100-100: Bare URL used

(MD034, no-bare-urls)

🤖 Prompt for AI Agents
In react_on_rails_pro/docs/code-splitting-loadable-components.md around line
100, there is a bare URL ("https://loadable-components.com/docs/babel-plugin/")
that violates MD034; replace it with markdown link syntax by wrapping the URL in
either inline link form [link
text](https://loadable-components.com/docs/babel-plugin/) or angle-bracketed
form <https://loadable-components.com/docs/babel-plugin/>—prefer using a
descriptive link text such as [Loadable Components Babel
Plugin](https://loadable-components.com/docs/babel-plugin/) for clarity.

@claude
Copy link

claude bot commented Nov 26, 2025

Code Review - PR #2127: Update spec/dummy for React 19 compatibility

✅ Overall Assessment

This is a well-structured upgrade PR that properly updates the test dummy apps to React 19. The changes are focused, consistent, and follow best practices for the dependency upgrades involved.


🎯 Strengths

1. Consistent Migration Pattern

  • ✅ All instances of redux-thunk import correctly updated from default export to named export ({ thunk })
  • ✅ React Helmet migration applied consistently across both open-source and Pro dummy apps
  • ✅ Thread-safe server-side rendering pattern correctly implemented with HelmetProvider context

2. Proper React 19 Dependency Chain

The dependency updates follow the correct upgrade path:

  • react 18 → 19 ✅
  • react-redux 8.x → 9.2.0 (React 19 compatible) ✅
  • redux 4.x → 5.0.1 (required by react-redux 9.x) ✅
  • redux-thunk 2.x → 3.1.0 (ESM-compatible, required by redux 5.x) ✅

3. Thread-Safe Helmet Implementation

The server-side rendering changes for react-helmet are architecturally sound:

const helmetContext = {};
const componentHtml = renderToString(
  <HelmetProvider context={helmetContext}>
    <ReactHelmet {...props} />
  </HelmetProvider>
);
const { helmet } = helmetContext;

This per-request context pattern prevents race conditions in multi-threaded environments.

4. Defensive Null Checking

Good defensive programming with helmet ? helmet.title.toString() : '' guards against edge cases.


⚠️ Areas for Improvement

1. CHANGELOG Missing ⚠️

Issue: No CHANGELOG entry was added.

Per CLAUDE.md guidelines:

Update CHANGELOG.md for user-visible changes only (features, bug fixes, breaking changes, deprecations, performance improvements)

Recommendation: While this is a test/dummy app change, it documents important React 19 compatibility. Consider adding an entry:

#### Fixed
[PR 2127](https://github.com/shakacode/react_on_rails/pull/2127) by [justin808](https://github.com/justin808): Update spec/dummy apps for React 19 compatibility. Upgraded React to 19.0.0, redux to 5.x, react-redux to 9.x, and migrated from react-helmet to @dr.pogodin/react-helmet for thread-safe server-side rendering.

Or at minimum document React 19 support validation in the next release notes.

2. Test Coverage Verification Needed 🧪

Status: CI is still running, but based on existing tests:

Covered areas:

  • spec/dummy/spec/requests/server_render_check_spec.rb - Tests server rendering (covers Redux changes)
  • spec/dummy/spec/system/integration_spec.rb - Tests ReactHelmetApp rendering

Recommendations:

  1. Verify CI passes completely - especially integration tests
  2. Manual smoke test: Run the dummy app and test:
    • ReactHelmet renders correctly with custom title
    • Redux components work with new middleware
    • Server-side rendering produces correct helmet metadata

3. Documentation Gap - React Helmet Migration

Issue: The migration from react-helmet to @dr.pogodin/react-helmet is a significant change that affects users.

Consider adding:

  • A note in documentation about the recommended React 19 helmet package
  • Migration guide snippet showing the HelmetProvider pattern
  • Or at least a comment in the example code explaining why the fork is used

4. Pro Package Consistency Check

Observation: Pro dummy app uses the same dependencies and patterns. Good!

Verify: The Pro-specific async rendering (lines 19-29 in ReactHelmetApp.server.jsx) still works correctly with the new helmet implementation.


🔍 Code Quality Assessment

Redux Middleware Changes

- import middleware from 'redux-thunk';
+ import { thunk } from 'redux-thunk';
- applyMiddleware(middleware)
+ applyMiddleware(thunk)

✅ Correct: Redux-thunk 3.x exports thunk as a named export (ESM standard).

React Helmet Server Pattern

const helmetContext = {};
const componentHtml = renderToString(
  <HelmetProvider context={helmetContext}>
    <ReactHelmet {...props} />
  </HelmetProvider>
);
const { helmet } = helmetContext;

✅ Excellent: This is the correct thread-safe pattern for @dr.pogodin/react-helmet.

Null Safety

title: helmet ? helmet.title.toString() : ''

✅ Good defensive programming: Handles edge case where helmet might be undefined.


🔒 Security & Performance

  • ✅ No security concerns identified
  • ✅ No performance regressions expected
  • ✅ Dependency versions are stable releases (not pre-release)
  • ⚠️ Consider verifying @dr.pogodin/react-helmet is actively maintained

📋 Testing Checklist

Before merging, confirm:

  • All CI tests pass (currently in progress)
  • Integration tests specifically cover ReactHelmetApp rendering
  • Redux app tests pass with new middleware
  • Manual test: Dummy app runs and renders correctly
  • Manual test: Server-rendered HTML includes correct helmet data
  • Consider: Pro package async helmet rendering works correctly

🎓 Adherence to Repository Guidelines

Follows CLAUDE.md:

  • Consistent pattern across all changes
  • Proper React 19 upgrade path
  • Thread-safe SSR implementation

⚠️ Missing:

  • CHANGELOG entry (recommended per guidelines)

🚀 Recommendation

APPROVE with minor suggestions:

  1. Add CHANGELOG entry documenting React 19 support validation
  2. Verify CI passes completely before merging
  3. Consider adding a comment in the React Helmet examples explaining the fork rationale
  4. Run manual smoke test on the dummy app to verify rendering

This is solid foundational work for React 19 support. The code quality is high, patterns are correct, and the migration is consistent. Great job! 🎉


Generated with Claude Code

Update shakapacker gem from 9.3.0 to 9.4.0 to match npm package version.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@claude
Copy link

claude bot commented Nov 26, 2025

PR Review: React 19 Compatibility Updates

I've reviewed this PR for code quality, potential issues, performance, security, and test coverage. Overall, this is a well-structured upgrade with proper migration patterns. Here are my findings:


Strengths

1. Comprehensive Dependency Updates

  • All dependency version bumps are correct and necessary for React 19 compatibility
  • Redux stack properly upgraded together (redux 4→5, react-redux 8→9, redux-thunk 2→3)
  • The migration from react-helmet to @dr.pogodin/react-helmet is the right choice (thread-safe, React 19 compatible)

2. Consistent Migration Patterns

  • All redux-thunk imports correctly changed from default export to named export
  • HelmetProvider consistently added across all client/server entry points
  • Server-side rendering properly uses context pattern for thread-safety

3. Good Documentation

  • Comments explain why HelmetProvider is needed
  • PR description clearly documents all changes
  • CLAUDE.md update about testing is valuable

🔍 Issues & Suggestions

Critical: Missing Defensive Check

In ReactHelmetApp.server.jsx (line 33):

title: helmet ? helmet.title.toString() : '',

Issue: While you check if helmet exists, you don't check if helmet.title exists before calling .toString().

Risk: If helmet exists but title is undefined, this will throw Cannot read property 'toString' of undefined.

Recommendation: Use optional chaining:

title: helmet?.title?.toString() || '',
link: helmet?.link?.toString() || '',
meta: helmet?.meta?.toString() || '',
style: helmet?.style?.toString() || '',

This pattern should be applied in all server rendering files:

  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetApp.server.jsx
  • react_on_rails/spec/dummy/client/app/startup/ReactHelmetAppBroken.server.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-hmr.jsx
  • react_on_rails_pro/spec/dummy/client/app/loadable/loadable-server.imports-loadable.jsx
  • react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/ReactHelmetApp.server.jsx

Minor: Code Consistency

1. File Extension Inconsistency

You renamed:

  • loadable-client.imports-loadable.js.jsx
  • loadable-server.imports-hmr.jsx (already .jsx)

Good! But verify all files using JSX have .jsx extension for consistency.

2. CLAUDE.md Location

The CLAUDE.md changes add a "COMMIT AND PUSH BY DEFAULT" section. This is helpful guidance but:

  • Consider if this belongs in a separate PR (mixing project instructions with dependency upgrades)
  • The guidance is more about Claude Code workflow than React 19 migration

🎯 Testing Recommendations

Based on CLAUDE.md guidelines, ensure you've tested:

# 1. Clean install (CRITICAL)
rm -rf node_modules
pnpm install --frozen-lockfile

# 2. Build all packages
pnpm run build

# 3. Test dummy app
cd react_on_rails/spec/dummy
pnpm run build:test

# 4. Run integration tests
bundle exec rake run_rspec:dummy

# 5. Test React Helmet SSR specifically
# - Navigate to React Helmet test pages
# - Verify <title> tags render correctly on server
# - Check browser console for hydration errors
# - Verify helmet data in page source (view-source:)

Key tests for React Helmet migration:

  • Server-rendered pages show correct <title> in HTML source
  • Client hydration doesn't cause React warnings
  • Thread-safety: Run concurrent requests to helmet pages (Pro SSR pool)

🔒 Security Considerations

No security concerns identified. The dependency updates are:

  • From official, maintained packages
  • Moving to more secure/maintained fork (@dr.pogodin/react-helmet)
  • Redux stack updates include security fixes

Performance Considerations

Neutral to positive performance impact:

  • Redux 5.x has performance improvements over 4.x
  • React 19 has better concurrent rendering
  • @dr.pogodin/react-helmet is more efficient than old react-helmet

No performance regressions expected.


📋 Test Coverage

Question: Are there existing tests that cover:

  1. Server-side rendering with React Helmet?
  2. Redux store creation with thunk middleware?
  3. Loadable components with React 19?

Recommendation: Ensure integration tests exercise these code paths:

  • spec/dummy/spec/ should have tests for helmet rendering
  • Test both client and server rendering paths
  • Verify no React 19 deprecation warnings in test output

📝 Changelog

Per CLAUDE.md guidelines:

  • ✅ This is a user-visible change (React 19 support)
  • ✅ Should be documented in CHANGELOG.md
  • Suggested entry:
#### [PR 2127](https://github.com/shakacode/react_on_rails/pull/2127) by [justin808](https://github.com/justin808)

**Added React 19 support** for spec/dummy test applications. Updated Redux stack (redux 4→5, react-redux 8→9, redux-thunk 2→3) and migrated from `react-helmet` to `@dr.pogodin/react-helmet` for thread-safe SSR. Updated all server rendering functions to use HelmetProvider context pattern.

Note: This updates the test/example applications only. Main library compatibility verified.

Final Recommendation

Approve with minor fixes needed:

  1. MUST FIX: Add optional chaining to all helmet.title.toString() calls (5 files)
  2. SHOULD TEST: Run full integration test suite locally before merging
  3. NICE TO HAVE: Separate CLAUDE.md changes into a different PR

The migration approach is solid and follows React 19 best practices. Once the defensive checks are added, this should be safe to merge.


🤖 Review Process

This review was performed according to CLAUDE.md guidelines, checking:

  • ✅ Code quality and best practices
  • ✅ Potential bugs or issues (found 1 critical)
  • ✅ Performance considerations
  • ✅ Security concerns
  • ✅ Test coverage
  • ✅ Changelog requirements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants