Welcome to your traffic light composition! I'm your mentor, and I'll guide you step-by-step to learn React useEffect, timers, and state machines with a modern TypeScript setup.
Difficulty: Beginner
Estimated time: 1–2 hours
Build a traffic light component that automatically cycles through red, yellow, and green lights at predetermined intervals. Learn React useEffect, setTimeout, cleanup functions, and state machine patterns.
A traffic light is a state machine that cycles through different colors (states) at fixed intervals. Think of it like a timer that automatically switches between colors—green means go, yellow means caution, and red means stop. In programming, this teaches you how to manage time-based state transitions and handle side effects in React.
Why Traffic Lights Matter:
- They demonstrate state machines—a fundamental programming pattern
- Building one teaches you React
useEffectand timer management - They show how to handle cleanup to prevent memory leaks
- Understanding timers is essential for animations, polling, and scheduled tasks
- They're a common interview question that tests your understanding of React hooks
- Understand how to use
useEffectfor side effects - Implement timers with
setTimeoutand cleanup withclearTimeout - Build a state machine pattern in React
- Manage component lifecycle and prevent memory leaks
- Use TypeScript interfaces for component configuration
- Node.js 18+ installed
- Basic knowledge of React and TypeScript
- Comfort with the terminal and
npm - Understanding of
useStatefrom previous compositions
npm --versionworks- Port 5173 available (Vite dev server)
- Git configured (
git --version) - Editor with TypeScript and ESLint plugins
npm install- Frontend-only:
npm run dev→ openhttp://localhost:5173
- Unit/Integration (Jest):
npm run test - Watch mode:
npm run test:watch
npm run format
npm run linttraffic-light/
├── client/
│ ├── index.html
│ └── src/
│ ├── App.tsx
│ ├── TrafficLight.tsx
│ ├── main.tsx
│ ├── styles.css
│ └── __tests__/
├── docs/
│ ├── description.md
│ └── solution.md
├── README.md
├── vite.config.ts
├── tsconfig.json
├── jest.config.js
└── eslint.config.js
- Frontend (Vite):
http://localhost:5173
dev: Vite dev serverbuild:tsc -b && vite buildlint: ESLint checktypecheck: TypeScript type checksformat: Prettier writeformat:check: Prettier checktest: Jest (unit/integration)test:watch: Jest watch modepreview: Vite preview (built app)
Always include:
vite.config.ts(with@alias toclient/src)jest.config.js(client jsdom project)eslint.config.js.prettierrctsconfig.json(paths@/*→client/src/*)components.json(shadcn/ui)Dockerfile(for CI/grading)
- Create config object with red, yellow, green colors
- Each color has
backgroundColor,duration, andnextproperties - Red light: 4000ms duration, next: 'green'
- Yellow light: 500ms duration, next: 'red'
- Green light: 3000ms duration, next: 'yellow'
- TrafficLight component accepts
configprop - Component uses
useStateto track current color - Component uses
useEffectto set up timer - Timer transitions to next color after duration
- Cleanup function clears timer on unmount
- Only active light has backgroundColor style
- Component has aria-label for accessibility
- No console errors
Your solution is complete when:
- ✓ Traffic light renders with three lights
- ✓ Lights cycle through green → yellow → red → green
- ✓ Each light displays for the correct duration
- ✓ Timer cleanup prevents memory leaks
- ✓ No console errors
- ✓ All tests pass
- ✓ Type checks pass (
npm run typecheck) - ✓ Lint passes (
npm run lint)
- Functionality: 50%
- Code Structure and Types: 20%
- useEffect and Cleanup: 20%
- Code Quality (lint/format): 10%
Start simple, then refine. Layered guidance:
- First nudge: "Use
useStateto track the current color state." - Deeper: "Use
useEffectwithsetTimeoutto transition colors after the duration." - Deepest: "Remember to return a cleanup function from
useEffectthat callsclearTimeoutto prevent memory leaks."
-
Problem:
npm installfails
Solution: Ensure Node 18+ is installed and tryrm -rf node_modules && npm cache clean --force && npm install. -
Problem: Frontend 5173 already in use
Solution: Stop the conflicting process or change the Vite port invite.config.ts. -
Problem: Tests fail unexpectedly
Solution: Runnpm run test:watchand read failing test expectations; ensure you're using fake timers correctly. -
Problem: Timer doesn't cleanup
Solution: Make sure youruseEffectreturns a cleanup function that callsclearTimeout(timerId). -
Problem: Component updates after unmount
Solution: Ensure cleanup function is properly clearing the timer to prevent "setState on unmounted component" errors.
Recommended flow:
- Create a feature branch:
git checkout -b feature/traffic-light
- Commit with conventional messages:
git add . git commit -m "feat: implement traffic light component"
- Push:
git push origin feature/traffic-light
- Run
npm run lintandnpm run formatbefore committing - Prefer explicit types; avoid
anywhen possible - Organize imports: external → internal → types
- Use
@/path aliases for internal modules
- Use
// TODO:(short, task-focused) - Place inline where the change is needed
- Keep TODOs concise
- React
useEffecthook for side effects setTimeoutandclearTimeoutfor timers- Cleanup functions to prevent memory leaks
- State machine pattern
- Component lifecycle management
After finishing:
- Add pause/resume functionality
- Support custom color sequences
- Add sound effects for each transition
- Implement horizontal layout option
- Add animation transitions between colors
Include:
- Problem Statement and Details
- Use Cases (Primary/Secondary)
- Constraints (Technical + Business Rules)
- Test Data (schemas and examples)
- Requirements Checklist
- Examples and Edge Cases
- Acceptance Criteria
- Hints
Good luck, and happy building!
Your React Development Mentor