Skip to content

chore: React Router v7.9.1 へのアップデートと Middleware API の変更対応#25

Merged
coji merged 1 commit intomainfrom
chore/bump
Sep 13, 2025
Merged

chore: React Router v7.9.1 へのアップデートと Middleware API の変更対応#25
coji merged 1 commit intomainfrom
chore/bump

Conversation

@coji
Copy link
Owner

@coji coji commented Sep 13, 2025

React Router を v7.7.1 から v7.9.1 へアップデートし、それに伴う Middleware API の破壊的変更に対応しました。
また、関連する各種依存パッケージも最新版に更新しています。

主な変更点

  • React Router のアップデート

    • react-router, react-router-dom, @react-router/dev などを v7.9.1 に更新しました。
  • Middleware API の変更対応

    • react-router.config.tsunstable_middleware フラグを v8_middleware に変更しました。
    • ルートファイル (route.ts, route.tsx) の unstable_clientMiddlewareclientMiddleware にリネームしました。
    • unstable_createContextreact-router から import する安定版の createContext に置き換えました。
    • コンテキスト名を userContext から authContext に変更し、役割を明確化しました。
  • 依存パッケージの更新

    • pnpm update を実行し、Vite, TypeScript, Biome, Firebase 関連など、プロジェクト全体の依存関係を更新しました。
  • 設定ファイルの更新

    • .vscode/settings.json: Biome の設定を quickfix.biome から source.fixAll.biome に更新しました。
    • biome.json: スキーマバージョンを更新し、globals.css を対象外に設定しました。

Summary by CodeRabbit

  • New Features

    • None
  • Refactor

    • Unified authentication context across the app for consistent user access.
    • Adopted stable middleware export names for improved compatibility.
  • Chores

    • Upgraded dependencies (including React Router 7.9.1, Tailwind 4.1.13, TypeScript 5.9.2, Biome 2.2.4, and others) for stability and performance.
    • Updated formatting scripts to the experimental Prettier CLI.
    • Refreshed configuration flags to align with the latest framework version.
    • Updated linting/schema configuration and editor on-save actions.

@coderabbitai
Copy link

coderabbitai bot commented Sep 13, 2025

Walkthrough

Replaces deprecated userContext with a new authContext and updates middleware/types to stable React Router APIs. Renames client middleware exports, aligns config flags with v8_middleware, bumps dependencies and tooling (React Router, Biome, Tailwind, etc.), adjusts Prettier CLI flags, and updates Biome schema and includes.

Changes

Cohort / File(s) Change summary
Auth context introduction & old removal
app/middlewares/auth-context.ts, app/middlewares/user-context.ts
Added authContext via `createContext<AppUser
Middleware: stable APIs and context key swap
app/middlewares/on-boarding-auth-middleware.ts, app/middlewares/optional-auth-middleware.ts
Switched to type MiddlewareFunction import; replaced userContext usage with authContext in context.set(...).
Routes: read user from authContext
app/routes/$handle+/_index/route.tsx, app/routes/$handle+/posts.$id._index/route.tsx, app/routes/$handle+/posts.$id.delete/route.tsx, app/routes/$handle+/posts.$id.edit/route.tsx, app/routes/welcome+/create_account/route.tsx
Replaced imports and lookups from userContext to authContext; no functional flow changes.
Client middleware export rename
app/routes/$handle+/_layout/route.tsx, app/routes/welcome+/_layout/route.ts
Renamed unstable_clientMiddlewareclientMiddleware; values unchanged.
React Router config flag update
react-router.config.ts
future.unstable_middleware: truefuture.v8_middleware: true.
Editor/tooling config tweaks
.vscode/settings.json, biome.json
VS Code on-save action: quickfix.biomesource.fixAll.biome. Biome schema 2.1.3 → 2.2.4; added files.includes: ["**", "!app/styles/globals.css"].
Dependency and script updates
package.json
Upgraded React Router, Biome, Tailwind, TypeScript, Vite, and others; updated Prettier scripts to use --experimental-cli with cache.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant R as Router
  participant MW as Middleware
  participant C as Context
  participant Rt as Route (loader/action)

  U->>R: Navigates / requests
  R->>MW: Invoke client/server middleware
  MW->>C: context.set(authContext, user)
  Note right of C: Stores AppUser|null under authContext
  R->>Rt: Dispatch loader/action
  Rt->>C: context.get(authContext)
  C-->>Rt: AppUser|null
  Rt-->>R: Response / redirect
  R-->>U: Render page
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

A hop and a swap in the meadow of code,
I nudged userContext down the old road.
authContext blooms where carrots are new,
Middleware trails in a stable hue.
With Biome groomed and routes aligned,
I thump approval—updates 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 succinctly identifies the primary work—upgrading React Router to v7.9.1 and adapting the Middleware API—so it accurately reflects the PR's main changes and aligns with the provided objectives and file diffs. It is specific, concise, and avoids irrelevant detail or file lists.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/bump

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.

@github-actions
Copy link

Visit the preview URL for this PR (updated for commit ff8492f):

https://remix-spa-example--pr25-chore-bump-jfswclvx.web.app

(expires Sat, 20 Sep 2025 13:39:27 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 48e666b485811f0b1bcd4fa4838b32a205a3ce05

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
package.json (1)

65-67: Update package.json engines.node to >=20.19.0

Vite 7.x needs Node 20.19+ (React Router v7 requires Node 20+), so "node": ">=18.0.0" is insufficient — change package.json (lines 65–67) to require Node >=20.19.0 (or bump to a recent Node 22/24 LTS).

app/routes/$handle+/_index/route.tsx (1)

39-45: Return proper HTTP status instead of throwing a generic Error in clientAction

Align with other routes and avoid 500s by using 401/403.

Apply:

-  const user = context.get(authContext)
-  if (user?.handle !== handle) {
-    throw new Error('Unauthorized')
-  }
+  const user = context.get(authContext)
+  if (!user) {
+    throw data(null, { status: 401 })
+  }
+  if (user.handle !== handle) {
+    throw data(null, { status: 403 })
+  }
🧹 Nitpick comments (6)
app/routes/welcome+/_layout/route.ts (1)

4-4: (Optional) Add a type guard for middleware array

Annotating helps catch accidental non-middleware entries.

-export const clientMiddleware = [onBoardingAuthMiddleware]
+export const clientMiddleware = [onBoardingAuthMiddleware] satisfies Array<import('react-router').MiddlewareFunction>
biome.json (1)

2-5: Check Biome files scope vs build artifacts

With "files.includes": ["**", "!app/styles/globals.css"], Biome could scan build outputs unless ignored elsewhere. Consider excluding common artifacts here too for speed.

   "files": {
-    "includes": ["**", "!app/styles/globals.css"]
+    "includes": ["**", "!app/styles/globals.css", "!**/build", "!**/dist", "!**/coverage"]
   },
package.json (1)

31-31: Pin radix-ui in package.json — don't use "latest"

package.json (line 31) currently has "radix-ui": "latest". pnpm-lock.yaml shows it resolved to 1.4.3 — change to a pinned semver (e.g. ^1.4.3 or 1.4.3) to avoid surprise upgrades.

File: package.json
Lines: 31-31

    "radix-ui": "latest",
app/middlewares/auth-context.ts (1)

1-4: (Nit) Add a brief doc comment

Improves discoverability in editors.

-import { createContext } from 'react-router'
+import { createContext } from 'react-router'
 import type { AppUser } from '~/services/auth'
 
-export const authContext = createContext<AppUser | null>()
+/**
+ * Authenticated user context for middleware → route data flow.
+ * Null when unauthenticated.
+ */
+export const authContext = createContext<AppUser | null>()
app/routes/welcome+/create_account/route.tsx (1)

29-33: Handle missing user with redirect (graceful failure path)

This route should be behind onboarding auth, but a defensive redirect avoids a 500 if context isn’t set.

Apply:

-  if (!user) {
-    throw new Error('システムエラー: ユーザ情報がありません')
-  }
+  if (!user) {
+    throw redirect('/')
+  }
app/routes/$handle+/posts.$id.delete/route.tsx (1)

24-29: Differentiate 401 vs 403 for clearer auth semantics

Return 401 when unauthenticated and 403 when authenticated but not the owner.

Apply:

-  const user = context.get(authContext)
-  if (user?.handle !== handle) {
-    // 本人でなければ削除できない
-    throw data(null, { status: 401 })
-  }
+  const user = context.get(authContext)
+  if (!user) {
+    throw data(null, { status: 401 })
+  }
+  if (user.handle !== handle) {
+    // 本人でなければ削除できない
+    throw data(null, { status: 403 })
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf94b3e and ff8492f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (15)
  • .vscode/settings.json (1 hunks)
  • app/middlewares/auth-context.ts (1 hunks)
  • app/middlewares/on-boarding-auth-middleware.ts (1 hunks)
  • app/middlewares/optional-auth-middleware.ts (1 hunks)
  • app/middlewares/user-context.ts (0 hunks)
  • app/routes/$handle+/_index/route.tsx (3 hunks)
  • app/routes/$handle+/_layout/route.tsx (1 hunks)
  • app/routes/$handle+/posts.$id._index/route.tsx (2 hunks)
  • app/routes/$handle+/posts.$id.delete/route.tsx (2 hunks)
  • app/routes/$handle+/posts.$id.edit/route.tsx (3 hunks)
  • app/routes/welcome+/_layout/route.ts (1 hunks)
  • app/routes/welcome+/create_account/route.tsx (2 hunks)
  • biome.json (1 hunks)
  • package.json (1 hunks)
  • react-router.config.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • app/middlewares/user-context.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: coji
PR: coji/remix-spa-example#8
File: app/routes/auth+/sign_out/route.tsx:1-1
Timestamp: 2025-02-19T12:11:06.825Z
Learning: React Router v7.2 introduced the href utility for type-safe routing, which should be imported from 'react-router' instead of 'remix-run/react'.
📚 Learning: 2025-02-19T12:11:06.825Z
Learnt from: coji
PR: coji/remix-spa-example#8
File: app/routes/auth+/sign_out/route.tsx:1-1
Timestamp: 2025-02-19T12:11:06.825Z
Learning: React Router v7.2 introduced the href utility for type-safe routing, which should be imported from 'react-router' instead of 'remix-run/react'.

Applied to files:

  • app/middlewares/on-boarding-auth-middleware.ts
🧬 Code graph analysis (10)
app/routes/$handle+/posts.$id._index/route.tsx (1)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
app/middlewares/auth-context.ts (1)
app/services/auth.ts (1)
  • AppUser (18-20)
app/routes/welcome+/_layout/route.ts (2)
app/routes/$handle+/_layout/route.tsx (1)
  • clientMiddleware (5-5)
app/middlewares/on-boarding-auth-middleware.ts (1)
  • onBoardingAuthMiddleware (5-17)
app/routes/$handle+/posts.$id.delete/route.tsx (1)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
app/routes/$handle+/_layout/route.tsx (2)
app/routes/welcome+/_layout/route.ts (1)
  • clientMiddleware (4-4)
app/middlewares/optional-auth-middleware.ts (1)
  • optionalAuthMiddleware (5-12)
app/routes/welcome+/create_account/route.tsx (1)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
app/routes/$handle+/posts.$id.edit/route.tsx (1)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
app/routes/$handle+/_index/route.tsx (1)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
app/middlewares/optional-auth-middleware.ts (2)
app/services/auth.ts (1)
  • isAuthenticated (107-138)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
app/middlewares/on-boarding-auth-middleware.ts (2)
app/services/auth.ts (1)
  • requireAuth (146-151)
app/middlewares/auth-context.ts (1)
  • authContext (4-4)
🔇 Additional comments (20)
react-router.config.ts (2)

6-6: Correct flag rename to v8_middleware

The migration from unstable_middleware → v8_middleware matches the v7→v8 middleware API stabilization. LGTM.


6-8: Sweep repo for leftover unstable APIs

ripgrep returned no matches; confirm there are no remaining usages of unstable_clientMiddleware, unstable_createContext, or middlewares/user-context — re-run the searches or manually verify (e.g. rg -nP '\bunstable_clientMiddleware\b|\bunstable_createContext\b' && rg -nP 'middlewares/(user-context)').

app/routes/welcome+/_layout/route.ts (1)

4-4: Export rename to clientMiddleware is consistent with v8 middleware API

Good alignment with the stable API.

.vscode/settings.json (1)

14-14: Switch to source.fixAll.biome is correct

Matches Biome’s recommended code action. LGTM.

package.json (1)

11-12: Prettier 3.6.2 supports --experimental-cli; handle cache in CI

Verified: Prettier 3.6.x added the experimental CLI and 3.6.2 supports --experimental-cli and it works with --cache.

  • Cache keys do NOT include plugin versions — clear the cache (or disable cache) after updating Prettier plugins to avoid stale formatting.
  • Default cache: ./node_modules/.cache/prettier/.prettier-cache (override with --cache-location).
  • Running Prettier without --cache will delete the cache; combining --cache with commands like --list-different can produce inconsistent/stale results — ensure CI clears/refreshes the cache before check runs or avoid --cache for deterministic CI checks.

File: package.json lines 11–12.

app/routes/$handle+/posts.$id._index/route.tsx (3)

7-7: authContext migration looks correct

Swapping to authContext and reading via context.get(authContext) is consistent with the new middleware API.

Also applies to: 19-21


3-3: Nice: href imported from react-router

Matches the prior learning to use the typed href from react-router.


29-49: Server-side authorization already enforced — original concern is incorrect

app/routes/$handle+/posts.$id.edit/route.tsx — clientLoader and clientAction call context.get(authContext) and throw 403 when user?.handle !== handle; app/routes/$handle+/posts.$id.delete/route.tsx — clientAction checks user?.handle !== handle and throws 401.

Likely an incorrect or invalid review comment.

app/middlewares/auth-context.ts (1)

4-4: Dedicated authContext established

Clean, typed context for AppUser | null. LGTM.

app/routes/$handle+/_layout/route.tsx (1)

5-5: Export rename to clientMiddleware is correct

Consistent with the v8 middleware API; no behavior change. LGTM.

app/routes/$handle+/_index/route.tsx (2)

16-16: authContext import looks good

Migration to the stable context is correct.


29-33: Context read in loader is correct

Null-safe usage and downstream isAuthor calculation are fine.

app/routes/welcome+/create_account/route.tsx (1)

8-8: authContext import migration is correct

Matches the new context module.

app/routes/$handle+/posts.$id.delete/route.tsx (1)

14-14: authContext import migration is correct

Consistent with the middleware change.

app/routes/$handle+/posts.$id.edit/route.tsx (3)

13-13: authContext import migration is correct

Move to stable createContext usage is appropriate.


35-43: Loader auth check is correct

Using 403 for “not your post” is appropriate; existence checks follow correctly.


51-56: Action auth check mirrors loader appropriately

Consistent 403 on handle mismatch; subsequent updates use user.uid safely.

app/middlewares/optional-auth-middleware.ts (1)

1-12: Middleware API migration looks correct

  • Imports the stable MiddlewareFunction type.
  • Stores user under authContext via context.set; compatible with downstream context.get calls.
app/middlewares/on-boarding-auth-middleware.ts (2)

1-4: Correct: use href from react-router and stable MiddlewareFunction

Matches our prior learning to import href from 'react-router'.


10-16: LGTM — config and route exports align; one check inconclusive

  • react-router.config.ts contains v8_middleware: true (line 6).
  • app/routes/welcome+/_layout/route.ts imports onBoardingAuthMiddleware (line 1) and exports clientMiddleware = [onBoardingAuthMiddleware] (line 4).
  • ripgrep reported "No files were searched" for the unstable_clientMiddleware check — re-run a plain search for "unstable_clientMiddleware" to confirm no remaining usages.

@coji coji merged commit a6b74d4 into main Sep 13, 2025
2 checks passed
@coji coji deleted the chore/bump branch September 13, 2025 13:59
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.

1 participant