Skip to content

React: Routing and Hooks - #3

Open
rika-milew wants to merge 111 commits into
unit-testingfrom
hooks-and-routing
Open

rika-milew wants to merge 111 commits into
unit-testingfrom
hooks-and-routing

Conversation

@rika-milew

@rika-milew rika-milew commented May 12, 2026

Copy link
Copy Markdown
Owner
  1. Task: https://github.com/rolling-scopes-school/tasks/blob/master/react/modules/tasks/functional-routing.md

  2. Screenshot:

image
  1. Deployment: https://rika-milew-rs-react-app.vercel.app/

  2. Done 18.05.2026 / deadline 19.05.2026

  3. Score: 100 / 100

  • Feature 1: Pagination (30 points)
  • Feature 2: Master-Detail View (45 points)
  • Feature 3: About Page (15 points)
  • Feature 4: 404 Page (10 points)

@vercel

vercel Bot commented May 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rika-milew-rs-react-app Ready Ready Preview, Comment May 29, 2026 10:11pm

@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Migrates to TanStack Router with file-based routes and RouterProvider. Converts class components to hooks. Adds SearchPage, NotFound, DetailView, and new hooks. Renames and hardens API services with timeouts and type guards. Updates tests, styles, and tooling (ESLint/Prettier/Stylelint/Vite/Vitest).

Changes

Router + Hooks Migration

Layer / File(s) Summary
End-to-end routing, data flow, UI, and tooling
src/router.ts, src/routes/*, src/App.tsx, src/pages/..., src/components/**/*, src/hooks/**/*, src/services/*, src/types/*, eslint.config.js, vite*.ts, package.json, stylelint.config.js, *.css, .husky/pre-push, .prettier*, vercel.json, src/test-utils/*, **/*.test.tsx
Adds TanStack Router and file routes; refactors UI to functional components; introduces data/detail/navigation/localStorage hooks; updates API services with timeouts and validation; aligns constants/types/guards; revises tests, styles, and tooling configs.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UI as SearchPage/CardList
  participant Router as TanStack Router
  participant Hooks as useDataList/useDetailData
  participant API as services/api

  User->>UI: Enter search / paginate / open detail
  UI->>Router: navigate({ search: { page } } or details)
  UI->>Hooks: loadData(search, page-1)
  Hooks->>API: getItems/getItemFull
  API-->>Hooks: Result (success/not-found/error)
  Hooks-->>UI: State update
  UI-->>User: Renders list/pagination/detail/error
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Comment thread src/components/button/button.tsx Outdated
Comment thread src/components/card-list/card-list.tsx Outdated
Comment thread src/components/card-list/card-list.tsx Outdated
Comment thread src/components/card-list/card-list.tsx
Comment thread src/components/card-list/card-list.tsx Outdated
Comment thread src/components/pagination/pagination.tsx
Comment thread src/components/card-list/card-list.tsx Outdated
@@ -0,0 +1,11 @@
import { ErrorBoundary } from '@/components/error-boundary/error-boundary';

export function ErrorBoundaryAdapter({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Couldn't we write defaultErrorComponent: ErrorBoundary?

@ansivgit

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

Caution

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

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

34-34: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove @types/p-limit (you’re on p-limit@7 which already ships types)

Informative React/TS student review: Lines 34 and 46: p-limit is pinned to ^7.3.0 while @types/p-limit is installed at ^2.1.0; p-limit@7.3.0 includes its own index.d.ts (types are exported from the package), and @types/p-limit@2.1.0 targets the legacy p-limit v2 API (export = pLimit, pLimit(concurrency: number) only), so this is version-mismatched and unnecessary. Action: remove @types/p-limit from devDependencies and rely on the bundled types from p-limit.

src/components/error-state/error-state.tsx (1)

13-18: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Lines 14-15: dynamically-rendered errors aren't announced to screen readers.

This block mounts only after a failed load, so assistive tech users get no notification that an error appeared. There's no semantic element that conveys "live" status, so this is a valid case for an ARIA live region: add role="alert" to the wrapping <div> (or to the <p>). That makes screen readers announce the message the moment it renders. Keep the rest as-is.

src/components/layout/footer/footer.module.css (1)

5-74: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Lines 6, 11, 49, 51, 64, 66, 72, 74: stylelint declaration-empty-line-before will fail CI.

The blank lines you've inserted to visually group declarations (box-model / color / etc.) each trip declaration-empty-line-before. These are reported as errors by Stylelint 17.12.0, so the lint step will break. Remove the empty lines that immediately precede a declaration, e.g.:

   align-items: center;
-
   width: 100%;

If the grouping whitespace is intentional, consider relaxing that rule in stylelint.config.js instead — otherwise the build stays red.

src/components/layout/header/header.module.css (1)

5-73: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Lines 6, 10, 15, 17, 25, 27, 73: same stylelint declaration-empty-line-before failures.

The blank lines preceding declarations here will be flagged as errors by Stylelint 17.12.0 and break CI. Drop the empty line before each declaration, or relax the rule in stylelint.config.js if the grouping whitespace is deliberate. Nice work on the .skip-link / :focus pattern, though — that's a solid keyboard-accessibility addition.

src/components/detail-view/detail-view.tsx (1)

21-50: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Lines 21-46: The keydown/click listeners and cleanup are wired correctly, and the [data-detail]/[data-card] guards prevent self-closing. One thing to be aware of: the effect re-subscribes on every render because closeDetailView has a new identity each render (see use-detail-navigation.ts) — listeners get removed/re-added needlessly. The real fix belongs in the hook (memoize the callbacks), which I've noted there; once that lands, this [closeDetailView] dependency becomes stable. The rest of the rendering logic (Lines 48-95) reads cleanly.

src/hooks/use-detail-navigation.ts (1)

9-29: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Lines 13-26: openDetailView and closeDetailView are recreated on every render, so any consumer that lists them in a dependency array (e.g. DetailView's useEffect keyed on closeDetailView) re-runs each render. Wrap each callback in useCallback with [navigate, search] as dependencies so their identities stay stable across renders. Also note navigate and search from TanStack Router are already render-stable inputs, so this gives you a clean, predictable dependency set. The useSearch({ from: '/_layout' }) adoption looks good — this is exactly the router-aware read suggested earlier.

src/services/data-service.ts (1)

1-10: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Lines 1-10: Duplicate imports from @/constants/constants

You're importing from the same module twice (lines 2 and 5-10). Consolidating these into a single import statement improves readability and follows common TS conventions.

Combine into one import block from @/constants/constants.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 195d0147-bf42-4a98-b1d5-9cde6ac5397b

📥 Commits

Reviewing files that changed from the base of the PR and between c0ccbcb and 5fb5ef9.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (67)
  • .prettierrc
  • eslint.config.js
  • package.json
  • src/components/button/button.module.css
  • src/components/button/button.tsx
  • src/components/card-list/card-list.module.css
  • src/components/card-list/card-list.test.tsx
  • src/components/card-list/card-list.tsx
  • src/components/card/card.module.css
  • src/components/card/card.test.tsx
  • src/components/card/card.tsx
  • src/components/detail-view/detail-view.module.css
  • src/components/detail-view/detail-view.test.tsx
  • src/components/detail-view/detail-view.tsx
  • src/components/error-boundary/error-boundary.module.css
  • src/components/error-boundary/error-boundary.test.tsx
  • src/components/error-button/error-button.test.tsx
  • src/components/error-state/error-state.module.css
  • src/components/error-state/error-state.test.tsx
  • src/components/error-state/error-state.tsx
  • src/components/layout/footer/footer.module.css
  • src/components/layout/footer/footer.test.tsx
  • src/components/layout/footer/footer.tsx
  • src/components/layout/header/header.module.css
  • src/components/layout/layout.module.css
  • src/components/layout/layout.test.tsx
  • src/components/layout/layout.tsx
  • src/components/loader/loader.module.css
  • src/components/loader/loader.tsx
  • src/components/pagination/pagination.module.css
  • src/components/pagination/pagination.test.tsx
  • src/components/pagination/pagination.tsx
  • src/components/search-bar/search-bar.module.css
  • src/components/search-bar/search-bar.test.tsx
  • src/components/search-bar/search-bar.tsx
  • src/constants/constants.ts
  • src/hooks/use-data-list.ts
  • src/hooks/use-detail-data.ts
  • src/hooks/use-detail-navigation.ts
  • src/hooks/use-local-storage.ts
  • src/main.tsx
  • src/pages/about/about-page.module.css
  • src/pages/about/about-page.tsx
  • src/pages/not-found/not-found.module.css
  • src/pages/not-found/not-found.test.tsx
  • src/pages/search/search-page.module.css
  • src/pages/search/search-page.test.tsx
  • src/pages/search/search-page.tsx
  • src/routes/-__root-component.tsx
  • src/routes/-_layout-component.tsx
  • src/routes/-_layout.details.$detailId-component.tsx
  • src/routes/__root.tsx
  • src/routes/_layout.details.$detailId.tsx
  • src/routes/_layout.tsx
  • src/services/api.test.tsx
  • src/services/api.ts
  • src/services/data-service.test.ts
  • src/services/data-service.ts
  • src/styles/index.css
  • src/styles/variables.css
  • src/test-utils/api-mock.ts
  • src/types/api.ts
  • src/types/type-guards.ts
  • stylelint.config.js
  • tsconfig.app.json
  • vite.config.ts
  • vitest.config.ts
💤 Files with no reviewable changes (1)
  • vitest.config.ts

Comment thread eslint.config.js
Comment thread src/components/error-boundary/error-boundary.module.css
Comment thread src/components/layout/layout.module.css
Comment thread src/components/layout/layout.tsx
Comment thread src/components/loader/loader.module.css
Comment thread src/components/search-bar/search-bar.module.css
Comment thread src/pages/about/about-page.module.css
Comment thread src/pages/not-found/not-found.module.css
Comment thread src/styles/index.css
Comment on lines +1 to +2
@import url('./variables.css');
@import url('./reset.css');

@coderabbitai coderabbitai Bot May 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Lines 1-2: Stylelint import-notation violation

Stylelint expects string notation for @import rather than url() syntax:

-@import url('./variables.css');
-@import url('./reset.css');
+@import './variables.css';
+@import './reset.css';
📝 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
@import url('./variables.css');
@import url('./reset.css');
`@import` './variables.css';
`@import` './reset.css';
🧰 Tools
🪛 Stylelint (17.12.0)

[error] 1-1: Expected "url('./variables.css')" to be "'./variables.css'" (import-notation)

(import-notation)


[error] 2-2: Expected "url('./reset.css')" to be "'./reset.css'" (import-notation)

(import-notation)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I suppose we should add the rule 'import-notation': 'string', at the stylelint-config

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@ansivgit, good thinking — but note that stylelint-config-standard (which stylelint.config.js already extends) already enforces import-notation: string. That's precisely why Stylelint flagged Lines 1–2. Adding the rule explicitly would be redundant (though harmless for clarity).

The two actionable paths are:

Option A – Fix the CSS (recommended, aligns with stylelint-config-standard):

-@import url('./variables.css');
-@import url('./reset.css');
+@import './variables.css';
+@import './reset.css';

Option B – Override the rule in stylelint.config.js to allow url() notation (if intentional):

rules: {
  'import-notation': 'url',   // allow url() syntax
  // ...other rules
}

Option A is the simpler fix and keeps the codebase consistent with the inherited standard. Option B makes sense only if there's a specific reason to prefer url() syntax here. Which would you prefer?


🧠 Learnings used
Learnt from: ansivgit
Repo: rika-milew/rs-react-app PR: 1
File: src/components/card/card.module.css:19-20
Timestamp: 2026-05-11T16:49:03.725Z
Learning: In this codebase, CSS relative color syntax (e.g., `hsl(from var(--color) h s l / alpha)`) is supported because the project targets modern browsers only (Chrome/Edge 131+, Firefox 133+, Safari 18+). When reviewing `.css` changes, do not require legacy fallback colors for relative color syntax unless the stylesheet explicitly opts into broader browser support.

@rika-milew rika-milew May 31, 2026

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

implemented in the app-state-management branch

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment thread src/styles/index.css
return (
<section className={cx('section')}>
<h2 className={cx('title')}>Results</h2>
{status === 'loading' && <Loader />}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
{status === 'loading' && <Loader />}
{isLoading && <Loader />}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

implemented in the app-state-management branch

Comment thread package.json
"typescript-eslint": "^8.58.2",
"vercel": "^54.0.0",
"vite": "^8.0.10",
"vite-tsconfig-paths": "^6.1.1",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yes, of course. Just keep in mind that this solution isn't optimal, so next time (for example, at the final task), it's better to look for a different solution to the issue.

Comment thread src/services/data-service.ts
Comment thread src/components/error-boundary/error-boundary.module.css
Comment thread src/styles/index.css
Comment on lines +1 to +2
@import url('./variables.css');
@import url('./reset.css');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I suppose we should add the rule 'import-notation': 'string', at the stylelint-config

globalThis.removeEventListener('keydown', handleKeyDown);
document.removeEventListener('click', handleOutsideClick);
};
}, [closeDetailView]);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it's better to wrap this function in a useCallback (in the useDetailNavigation hook). See Rabbit's comment.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

implemented in the app-state-management branch. There I completely removed this hook and used useCallback

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.

2 participants