Skip to content

Conversation

@navya-kedlaya
Copy link
Collaborator

@navya-kedlaya navya-kedlaya commented Aug 18, 2025

Description:
Upgraded React and related packages to React 19 and refactored client-side rendering logic to use createRoot and hydrateRoot from react-dom/client.
Adjusted package.json and package-lock.json to reflect new versions of React, ReactDOM, and React Redux.

Changes made in package.json:
React upgraded: ^16.14.0 → ^19.1.0
ReactDOM upgraded: ^16.14.0 → ^19.1.0
React Redux upgraded: ^7.2.5 → ^9.1.2

Verifications:
Application boots successfully with React 19 APIs.
Both render and hydrate flows tested locally.
Dependency resolved cleanly

Checklist:
Code builds without errors
Tests pass locally
Reviewers added

Summary by CodeRabbit

  • Chores
    • Bumped app version to 7.34.5-react-upgrade-v19.4, updated npm engine to ^10.0.0, and upgraded React stack (react, react-dom, react-redux) and several Quintype packages (amp, backend, components, seo).
  • Tests
    • Converted test files to CommonJS require style; test logic and expectations remain unchanged.

@coderabbitai
Copy link

coderabbitai bot commented Aug 18, 2025

Walkthrough

Bumps package version and npm engine and upgrades multiple dependencies (including React stack) in package.json. Converts several test files from ES module import to CommonJS require. Adds a single blank line to client/start.js. No runtime control-flow or logic changes.

Changes

Cohort / File(s) Summary
Package metadata & dependencies
package.json
version7.34.5-react-upgrade-v19.4. engines.npm ^8.5.0 → ^10.0.0. Upgrades: @quintype/amp2.22.1-version-upgrade.1, @quintype/backend2.7.1-version-upgrade.0, @quintype/components3.8.8-only-react-v19.3, @quintype/seo1.49.3-beta.0, react^19.2.0, react-dom^19.2.0, react-redux^9.2.0.
Test module syntax migration (ESM → CJS)
test/integration/amp-handler-test.js, test/unit/amp/amp-setcorsheaders-test.js, test/unit/create-store-test.js
Replaced ES module import statements with CommonJS require/destructuring. No logic or assertions changed.
Whitespace / formatting
client/start.js
Added a leading blank line before the module comment; no functional changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • nandap4790
  • VeenaYemmiganur

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title "React 19 upgrade" directly summarizes the main objective of the pull request, which is to upgrade React and related packages to React 19. According to the raw summary and PR objectives, this is the primary change across the changeset, with updates to React (^16.14.0 → ^19.2.0), react-dom, react-redux, and related Quintype dependencies. The title is concise, clear, and specific enough that a teammate scanning the history would immediately understand this is a React version upgrade. While the PR also includes other changes like npm engine updates and test file refactoring, the React upgrade is the dominant theme and the title appropriately reflects this main focus.
Description Check ✅ Passed The pull request description provides a mostly complete overview of the changes, including a clear description of the React 19 upgrade, specific version numbers for the main dependency changes, and a verifications section detailing that the application boots successfully and both render and hydrate flows were tested locally. However, the description does not strictly follow the provided template structure and is missing some template elements: it lacks explicit issue references (Fixes #, Dependencies #), no documentation link is provided, the "Type of change" checkbox section is not included, and the "How Has This Been Tested?" section is minimal compared to the template's expectations for detailed test cases and reproduction instructions. The core information about what was changed and how it was verified is present, though the template structure could be more thoroughly followed.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch react-upgrade-v19

📜 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 37c18b4 and 41ba468.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json (3 hunks)
⏰ 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). (1)
  • GitHub Check: default
🔇 Additional comments (3)
package.json (3)

8-8: Verify npm engine requirement bump to ^10.0.0 aligns with project requirements.

The npm engine constraint was bumped from ^8.5.0 to ^10.0.0. This is a significant increase that will require developers and CI to use npm 10+. Confirm this is:

  1. Intentional and necessary for React 19 / Node 20 compatibility,
  2. Aligned with the team's development and deployment environment.

57-59: React 19.2.0 and react-redux 9.2.0 versions look correct.

React and react-dom are correctly pinned to ^19.2.0, and react-redux was upgraded to ^9.2.0 (which officially declares React 19 support per prior verification). No concerns here.


36-40: Beta versions detected—confirm intentional and document rationale.

All four Quintype dependencies (lines 36–40) are officially published on npm but tagged as beta pre-release versions:

  • @quintype/amp@2.22.1-version-upgrade.1 (beta; latest stable: 2.22.5)
  • @quintype/backend@2.7.1-version-upgrade.0 (beta; latest stable: 2.7.0)
  • @quintype/components@3.8.8-only-react-v19.3 (beta; latest stable: 3.8.8)
  • @quintype/seo@1.49.3-beta.0 (beta; latest stable: 1.49.2)

These are not internal versions—they are official releases prepared for React 19 compatibility. However, using beta versions in production dependencies carries risk. Confirm this choice is intentional for this upgrade work and document why stable versions cannot be used at this time.


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.

Copy link

@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 (2)
client/start.js (2)

204-207: Optional: capture hydration warnings via onRecoverableError.

React 18/19 can surface hydration mismatches as recoverable errors. Wiring a handler helps observability in prod.

Example modification:

const root = hydrateRoot(containerEle, component, {
  onRecoverableError: (err) => console && console.error("Hydration recoverable error:", err)
});

208-212: Optional: cache roots per container to avoid multiple createRoot/hydrateRoot calls.

Calling createRoot/hydrateRoot more than once for the same container throws. If renderComponent might be invoked repeatedly for the same DOM id, cache and reuse the root.

Module-scope cache:

// Place at module scope
const __qtRoots = new Map(); // key: container id, value: root

Use it in renderComponent:

// For hydrate path
let root = __qtRoots.get(container);
if (!root) {
  root = hydrateRoot(containerEle, component);
  __qtRoots.set(container, root);
} else {
  root.render(component); // subsequent updates
}
return root;

// For non-hydrate path
let root = __qtRoots.get(container);
if (!root) {
  root = createRoot(containerEle);
  __qtRoots.set(container, root);
}
root.render(component);
return root;

If you’re unsure whether renderComponent can be called twice for the same container in your apps, I can scan the repo for repeated invocations per container id to gauge the risk.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 05a08d9 and 0fd4eef.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • client/start.js (2 hunks)
  • package.json (1 hunks)
  • test/integration/amp-handler-test.js (1 hunks)
  • test/unit/amp/amp-setcorsheaders-test.js (1 hunks)
  • test/unit/create-store-test.js (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
test/integration/amp-handler-test.js (3)
test/unit/amp/amp-setcorsheaders-test.js (1)
  • supertest (3-3)
server/amp/handlers/story-page.js (1)
  • require (7-7)
server/routes.js (15)
  • require (9-9)
  • require (10-10)
  • require (11-17)
  • require (19-19)
  • require (20-20)
  • require (21-21)
  • require (22-22)
  • require (23-23)
  • require (24-24)
  • require (25-25)
  • require (26-26)
  • require (30-30)
  • require (262-266)
  • require (627-627)
  • require (716-716)
test/unit/create-store-test.js (5)
test/unit/amp/amp-setcorsheaders-test.js (1)
  • require (4-4)
test/integration/amp-handler-test.js (1)
  • require (5-5)
server/api-client.js (1)
  • require (14-26)
server/routes.js (12)
  • require (9-9)
  • require (10-10)
  • require (11-17)
  • require (19-19)
  • require (20-20)
  • require (21-21)
  • require (22-22)
  • require (23-23)
  • require (24-24)
  • require (25-25)
  • require (26-26)
  • require (30-30)
assetify/client.js (1)
  • require (3-3)
test/unit/amp/amp-setcorsheaders-test.js (3)
test/integration/amp-handler-test.js (2)
  • supertest (4-4)
  • require (5-5)
test/unit/amp/amp-story-page-handler.js (2)
  • require (7-7)
  • require (8-8)
test/unit/amp/amp-get-domain-specific-opts.js (1)
  • require (2-2)
client/start.js (1)
server/render.js (1)
  • component (63-65)
🔇 Additional comments (4)
package.json (1)

57-59: Peer Dependencies & Legacy API Check Complete ✅

  • No ReactDOM.render or ReactDOM.hydrate calls remain.
  • No default import ReactDOM from 'react-dom' usages.
  • Only the root package.json declares React-related versions; no local packages declare a React peerDependency.

Next step: confirm that @quintype/components (and any other React-dependent libraries) list React 19 in their published peerDependencies. Please run:

npm view @quintype/components peerDependencies --json

and verify that "react" (and "react-dom", if present) ranges include ^19.0.0 to avoid install/runtime warnings.

test/unit/create-store-test.js (1)

1-1: LGTM: CommonJS require migration is correct.

The destructured require matches prior named imports and keeps test semantics unchanged.

test/integration/amp-handler-test.js (1)

4-5: LGTM: ES module → CommonJS migration for tests.

supertest and ampRoutes are required correctly; no behavioral changes introduced.

test/unit/amp/amp-setcorsheaders-test.js (1)

3-4: LGTM: ES module → CommonJS migration for tests.

Imports converted cleanly; route and assertions remain intact.

client/start.js Outdated
Comment on lines 204 to 212
const root = hydrateRoot(containerEle, component);
if (typeof callback === "function") callback();
return root;
}
return ReactDOM.render(component, containerEle, callback);
const root = createRoot(containerEle);
root.render(component);
if (typeof callback === "function") callback();
return root;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Callback now fires too early; restore post-commit semantics for render/hydrate.

With createRoot/hydrateRoot, invoking the callback immediately after calling render/hydrate no longer guarantees “after commit” timing (unlike ReactDOM.render/hydrate callbacks). This can cause premature effects (e.g., dispatching CLIENT_SIDE_RENDERED before the tree mounts).

Recommended: invoke the callback via a tiny component that runs a useEffect on commit. Remove the direct callback invocations here and wrap the rendered subtree instead.

Apply this diff to stop calling the callback immediately:

   if (props.hydrate) {
-    const root = hydrateRoot(containerEle, component);
-    if (typeof callback === "function") callback();
-    return root;
+    const root = hydrateRoot(containerEle, component);
+    return root;
   }
-  const root = createRoot(containerEle);
-  root.render(component);
-  if (typeof callback === "function") callback();
-  return root;
+  const root = createRoot(containerEle);
+  root.render(component);
+  return root;

And add this minimal helper + component construction (outside the selected range) to ensure the callback runs after the first commit:

// Add once near the top-level of this module
function CommitCallback({ onCommit }) {
  React.useEffect(() => {
    try {
      if (typeof onCommit === "function") onCommit();
    } catch (e) {
      console && console.error("Commit callback error:", e);
    }
  }, []);
  return null;
}

// Modify the element creation inside renderComponent (replace the `component` line)
const component = React.createElement(
  Provider,
  { store },
  React.createElement(
    React.Fragment,
    null,
    React.createElement(clazz, props || {}),
    typeof callback === "function" ? React.createElement(CommitCallback, { onCommit: callback }) : null
  )
);
🤖 Prompt for AI Agents
In client/start.js around lines 204 to 212, the callback is invoked immediately
after calling createRoot().render/hydrateRoot(), which fires too early; instead
add a small CommitCallback component near the top of the module that uses
useEffect to call the onCommit function after commit, remove the direct callback
invocations in this range, and change the rendered element to wrap the existing
Provider subtree in a fragment that includes the original component plus a
CommitCallback instance when a callback is provided so the callback runs inside
useEffect (post-commit) and errors are caught and logged.

Copy link

@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 (1)
package.json (1)

57-59: Move React packages to peerDependencies to prevent duplicate React and hooks/runtime errors

As a framework/library, depending on React/ReactDOM/React-Redux via "dependencies" can cause duplicate installations in consumer apps, leading to invalid hook calls and subtle runtime issues. Best practice is:

  • Declare them as peerDependencies (required from the host app)
  • Keep them in devDependencies for local testing/builds
  • Remove them from dependencies

Apply this diff to remove from "dependencies":

-    "react": "^19.1.0",
-    "react-dom": "^19.1.0",
-    "react-redux": "^9.1.2",

Then add these sections outside this hunk (illustrative JSON):

{
  "peerDependencies": {
    "react": "^19.1.0",
    "react-dom": "^19.1.0",
    "react-redux": "^9.1.2"
  },
  "devDependencies": {
    "react": "^19.1.0",
    "react-dom": "^19.1.0",
    "react-redux": "^9.1.2"
  }
}

If moving to peerDependencies is too disruptive right now, at minimum add matching peerDependencies in addition to dependencies to surface version mismatches during install.

Would you like me to generate a follow-up PR that migrates these to peerDependencies and updates docs/migration notes?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 173f429 and 0150836.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json (2 hunks)

package.json Outdated
{
"name": "@quintype/framework",
"version": "7.34.4",
"version": "7.34.5-react-upgrade-v19.1",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Major version bump required (breaking change) and avoid custom prerelease suffix

Upgrading React from 16.x to 19.x is a breaking change for consumers still on older React. The current version string reads like a patch prerelease of 7.x, which is misleading and can cause improper semver resolution. Also, your prepublishOnly runs a release script; manually bumping version may fight that automation.

Recommend either:

  • Let the release script perform a major bump (via a feat!: commit), or
  • Explicitly bump to 8.0.0 (or 8.0.0-rc.1 if you want a prerelease).

Apply this diff if you choose the explicit bump:

-  "version": "7.34.5-react-upgrade-v19.1",
+  "version": "8.0.0",

I can prep the conventional commit and release notes for the major bump if you want to keep it automated with your standard-version flow.

📝 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
"version": "7.34.5-react-upgrade-v19.1",
"version": "8.0.0",
🤖 Prompt for AI Agents
In package.json around lines 3 to 3, the current version
"7.34.5-react-upgrade-v19.1" is a misleading custom prerelease suffix for a
breaking React upgrade; either remove the custom tag and allow your release
automation to perform a proper major bump (use a feat!: conventional commit to
trigger it), or explicitly set the version to a correct semver major like
"8.0.0" (or "8.0.0-rc.1" for an official prerelease) and ensure you do not
conflict with the prepublishOnly release script by coordinating with or
disabling that script before committing the manual change.

Copy link

@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: 0

♻️ Duplicate comments (1)
package.json (1)

3-3: Use a proper semver major bump; drop custom prerelease suffix and align with release script

React 19 upgrade is a breaking change; the version string "7.34.5-react-upgrade-v19.3" is misleading and can fight your prepublishOnly release flow.

Suggested explicit bump:

-  "version": "7.34.5-react-upgrade-v19.3",
+  "version": "8.0.0",

If you rely on automated releases, prefer a feat!: commit and let standard-version bump major. Coordinate to avoid double-bumping.

🧹 Nitpick comments (2)
package.json (2)

6-9: Widen Node engine, reconsider npm engine pin

  • "^20.0.0" excludes Node 22 LTS; prefer ">=20" (or ">=20 <23") unless you intentionally disallow Node 22.
  • Pinning "npm" can block Yarn/PNPM users and older npm; consider removing or loosening.
   "engines": {
-    "node": "^20.0.0",
-    "npm": "^10.0.0"
+    "node": ">=20"
+    // consider removing "npm" or loosening it if kept
   },

57-59: React 19 + react-redux 9.2.0 looks good; for a library, prefer peerDependencies to avoid duplicate React

Current deps will force-install React for consumers, risking duplicate React copies (hooks/hydration issues). Recommend moving React, react-dom, react-redux to peerDependencies (and keep them in devDependencies for tests).

Option A (require React 19 only):

  • Remove from dependencies (apply within this block):
-    "react": "^19.2.0",
-    "react-dom": "^19.2.0",
-    "react-redux": "^9.2.0",
  • Add near the bottom:
"peerDependencies": {
  "react": ">=19 <20",
  "react-dom": ">=19 <20",
  "react-redux": ">=9.2.0 <10"
}

Option B (support React 18 and 19 if your codepaths allow):

"peerDependencies": {
  "react": ">=18 <20",
  "react-dom": ">=18 <20",
  "react-redux": ">=9.0.0 <10"
}

Please confirm your intended support matrix (18 vs 19) and I can generate the exact diff across sections.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1eecc1 and 37c18b4.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • package.json (2 hunks)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants