feat: Migrate Angular2-HN to React (Phases 1-3)#154
feat: Migrate Angular2-HN to React (Phases 1-3)#154devin-ai-integration[bot] wants to merge 1 commit intomasterfrom
Conversation
Phase 1: Setup & Foundation - Initialize React app with Vite + TypeScript - Set up folder structure: components/, services/, models/, hooks/, context/ - Install core dependencies: react-router-dom, axios Phase 1.2: Port Data Models - Migrate TypeScript interfaces from Angular: Story, User, Comment, Settings, FeedType, PollResult Phase 1.3: Port API Service - Convert HackerNewsAPIService to Promise-based service - Create custom hooks: useFeed, useItem, useUser - API endpoint: https://node-hnapi.herokuapp.com Phase 2: Core Components - App.tsx with React Router and Google Analytics tracking - Header component with navigation links and settings toggle - Footer component - Settings component with theme selection, font size, list spacing Phase 2.2: Settings & Theme System - SettingsContext with localStorage persistence - Dark mode detection via prefers-color-scheme - Three themes: Default, Night, Black (AMOLED) Phase 3: Feed Components - Feed component with pagination and scroll restoration - Item component with responsive design - Loader and ErrorMessage components Routes implemented: - /news/:page, /newest/:page, /show/:page, /ask/:page, /jobs/:page - /item/:id and /user/:id (placeholders for Phase 4) Co-Authored-By: Eashan Sinha <eashan.sinha@codeium.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| const darkColorSchemeMedia = typeof window !== 'undefined' | ||
| ? window.matchMedia('(prefers-color-scheme: dark)') | ||
| : null; |
There was a problem hiding this comment.
🔴 MediaQueryList object recreated on every render causes useEffect to run infinitely
The darkColorSchemeMedia variable is created on every render of SettingsProvider because window.matchMedia() returns a new object reference each time it's called.
Click to expand
Problem
At line 37-39, darkColorSchemeMedia is created during render:
const darkColorSchemeMedia = typeof window !== 'undefined'
? window.matchMedia('(prefers-color-scheme: dark)')
: null;This variable is then used as a dependency in the useEffect at line 66:
}, [darkColorSchemeMedia, handleSystemPreferredColorSchemeChange]);Since window.matchMedia() returns a new MediaQueryList object on each call, the reference changes on every render. This causes:
- The
useEffectto run on every render (not just on mount) - Event listeners to be constantly added and removed
- Potential performance degradation and unnecessary re-renders
Expected Behavior
The MediaQueryList should be created once and stored using useRef or useMemo so the effect only runs when necessary.
Impact
This causes unnecessary effect executions on every component re-render, leading to performance issues and potential memory leaks from rapid listener attachment/detachment.
Recommendation: Use useMemo or useRef to create the MediaQueryList once:
const darkColorSchemeMedia = useMemo(() =>
typeof window !== 'undefined'
? window.matchMedia('(prefers-color-scheme: dark)')
: null,
[]
);Was this helpful? React with 👍 or 👎 to provide feedback.
Migrate Angular2-HN to React (Phases 1-3)
Summary
This PR migrates the Angular 9 Hacker News PWA client to React with TypeScript. The migration covers Phases 1-3: Setup & Foundation, Core Components, and Feed Components. The React app is created in a new
react-app/directory alongside the existing Angular code.Key changes:
HackerNewsAPIServicefrom RxJS Observables to Promise-based axios calls with custom React hooks (useFeed,useItem,useUser)/news/:page,/newest/:page,/show/:page,/ask/:page,/jobs/:pageNot yet implemented (Phase 4):
/item/:id- Item details page (placeholder only)/user/:id- User profile page (placeholder only)Review & Testing Checklist for Human
Recommended test plan:
cd react-app && npm install && npm run devNotes
https://node-hnapi.herokuapp.comis the same as the original appLink to Devin run: https://app.devin.ai/sessions/5aa9183e8ce24b039120d16d666b0cf3
Requested by: Eashan Sinha (@eashansinha)