docs(30): create phase plan

Phase 30: Component Memoization
- 1 plan in 1 wave
- Wrap JKSessionAudioInputs with React.memo
- Wrap JKSessionRemoteTracks with React.memo
- Ready for execution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nuwan 2026-03-05 18:27:26 +05:30
parent 125a7cdcc2
commit 4fb81ea93e
2 changed files with 203 additions and 3 deletions

View File

@ -63,10 +63,10 @@ Plans:
2. JKSessionRemoteTracks wrapped with React.memo 2. JKSessionRemoteTracks wrapped with React.memo
3. Track components only re-render when their specific track data changes 3. Track components only re-render when their specific track data changes
4. React DevTools shows stable render counts for memoized components 4. React DevTools shows stable render counts for memoized components
**Plans**: TBD **Plans**: 1 plan
Plans: Plans:
- [ ] 30-01: TBD - [ ] 30-01-PLAN.md — Wrap JKSessionAudioInputs and JKSessionRemoteTracks with React.memo
### Phase 31: Selector Optimization ### Phase 31: Selector Optimization
**Goal**: Redux selectors compute efficiently with memoization **Goal**: Redux selectors compute efficiently with memoization
@ -105,7 +105,7 @@ Plans:
|-------|-----------|----------------|--------|-----------| |-------|-----------|----------------|--------|-----------|
| 28. VU Meter Optimization | v1.7 | 2/2 | ✓ Complete | 2026-03-05 | | 28. VU Meter Optimization | v1.7 | 2/2 | ✓ Complete | 2026-03-05 |
| 29. Context Optimization | v1.7 | 1/1 | ✓ Complete | 2026-03-05 | | 29. Context Optimization | v1.7 | 1/1 | ✓ Complete | 2026-03-05 |
| 30. Component Memoization | v1.7 | 0/TBD | Not started | - | | 30. Component Memoization | v1.7 | 0/1 | Planned | - |
| 31. Selector Optimization | v1.7 | 0/TBD | Not started | - | | 31. Selector Optimization | v1.7 | 0/TBD | Not started | - |
| 32. State Update Optimization | v1.7 | 0/TBD | Not started | - | | 32. State Update Optimization | v1.7 | 0/TBD | Not started | - |

View File

@ -0,0 +1,200 @@
---
phase: 30-component-memoization
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- jam-ui/src/components/client/JKSessionAudioInputs.js
- jam-ui/src/components/client/JKSessionRemoteTracks.js
autonomous: true
must_haves:
truths:
- "JKSessionAudioInputs does not re-render when parent re-renders with same props"
- "JKSessionRemoteTracks does not re-render when parent re-renders with same props"
- "Track components only re-render when their specific track data changes"
- "React DevTools shows components as 'Memo' with displayName"
artifacts:
- path: "jam-ui/src/components/client/JKSessionAudioInputs.js"
provides: "Memoized audio inputs container"
contains: "memo(function JKSessionAudioInputs"
- path: "jam-ui/src/components/client/JKSessionRemoteTracks.js"
provides: "Memoized remote tracks container"
contains: "memo(function JKSessionRemoteTracks"
key_links:
- from: "jam-ui/src/components/client/JKSessionScreen.js"
to: "JKSessionAudioInputs"
via: "stable props from memoized context"
pattern: "<JKSessionAudioInputs"
- from: "jam-ui/src/components/client/JKSessionScreen.js"
to: "JKSessionRemoteTracks"
via: "stable props from memoized context"
pattern: "<JKSessionRemoteTracks"
---
<objective>
Wrap JKSessionAudioInputs and JKSessionRemoteTracks with React.memo to prevent unnecessary re-renders when parent components re-render with unchanged props.
Purpose: Complete the component memoization chain started in Phase 29. These container components sit between JKSessionScreen (parent) and the already-memoized child components (JKSessionMyTrack, SessionTrackVU, SessionTrackGain). Without memoization, parent re-renders cascade through these containers even when props haven't changed.
Output: Two memoized container components that skip re-renders when props are shallowly equal.
</objective>
<execution_context>
@/Users/nuwan/.claude/get-shit-done/workflows/execute-plan.md
@/Users/nuwan/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/30-component-memoization/30-RESEARCH.md
@.planning/phases/29-context-optimization/29-01-SUMMARY.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Wrap JKSessionAudioInputs with React.memo</name>
<files>jam-ui/src/components/client/JKSessionAudioInputs.js</files>
<action>
Wrap JKSessionAudioInputs with React.memo following the Phase 29 pattern:
1. Add `memo` to the React import:
```javascript
import React, { memo } from 'react';
```
2. Wrap the component definition with memo using named function expression:
```javascript
const JKSessionAudioInputs = memo(function JKSessionAudioInputs({
myTracks,
chat,
mixerHelper,
isRemote = false,
mixType = 'default'
}) {
// existing implementation unchanged
});
```
3. Add displayName after the component definition (before export):
```javascript
JKSessionAudioInputs.displayName = 'JKSessionAudioInputs';
```
4. Keep the existing `export default JKSessionAudioInputs;` unchanged.
Note: Props are already stable from Phase 29 context memoization. Default shallow comparison is sufficient - do NOT add custom comparison function.
</action>
<verify>
Run syntax check:
```bash
cd jam-ui && node -c src/components/client/JKSessionAudioInputs.js
```
Verify memo wrapper present:
```bash
grep -n "memo(function JKSessionAudioInputs" jam-ui/src/components/client/JKSessionAudioInputs.js
```
Verify displayName present:
```bash
grep -n "displayName = 'JKSessionAudioInputs'" jam-ui/src/components/client/JKSessionAudioInputs.js
```
</verify>
<done>
JKSessionAudioInputs.js contains:
- `import React, { memo } from 'react'`
- `memo(function JKSessionAudioInputs` wrapper
- `displayName = 'JKSessionAudioInputs'`
- Syntax check passes
</done>
</task>
<task type="auto">
<name>Task 2: Wrap JKSessionRemoteTracks with React.memo</name>
<files>jam-ui/src/components/client/JKSessionRemoteTracks.js</files>
<action>
Wrap JKSessionRemoteTracks with React.memo following the same pattern:
1. Update the React import to add `memo`:
```javascript
import React, { useMemo, memo } from 'react';
```
2. Wrap the component definition with memo using named function expression:
```javascript
const JKSessionRemoteTracks = memo(function JKSessionRemoteTracks({
mixerHelper,
sessionModel
}) {
// existing implementation unchanged (includes useMemo for remoteParticipantsData)
});
```
3. Add displayName after the component definition (before export):
```javascript
JKSessionRemoteTracks.displayName = 'JKSessionRemoteTracks';
```
4. Keep the existing `export default JKSessionRemoteTracks;` unchanged.
Note: This component already uses useMemo internally for remoteParticipantsData. The memo wrapper prevents re-renders when mixerHelper and sessionModel props haven't changed.
</action>
<verify>
Run syntax check:
```bash
cd jam-ui && node -c src/components/client/JKSessionRemoteTracks.js
```
Verify memo wrapper present:
```bash
grep -n "memo(function JKSessionRemoteTracks" jam-ui/src/components/client/JKSessionRemoteTracks.js
```
Verify displayName present:
```bash
grep -n "displayName = 'JKSessionRemoteTracks'" jam-ui/src/components/client/JKSessionRemoteTracks.js
```
</verify>
<done>
JKSessionRemoteTracks.js contains:
- `import React, { useMemo, memo } from 'react'`
- `memo(function JKSessionRemoteTracks` wrapper
- `displayName = 'JKSessionRemoteTracks'`
- Syntax check passes
</done>
</task>
</tasks>
<verification>
After both tasks complete:
1. **Syntax verification** (automated):
```bash
cd jam-ui && node -c src/components/client/JKSessionAudioInputs.js && node -c src/components/client/JKSessionRemoteTracks.js
```
2. **Pattern verification** (automated):
```bash
grep -l "memo(function" jam-ui/src/components/client/JKSession{AudioInputs,RemoteTracks}.js | wc -l
# Expected: 2
```
3. **Manual verification** (optional - user can verify with React DevTools):
- Open session screen in browser
- Open React DevTools Profiler tab
- Record while triggering parent re-render (e.g., toggle a setting)
- Check JKSessionAudioInputs and JKSessionRemoteTracks show "Did not render" when props unchanged
</verification>
<success_criteria>
- Both components wrapped with React.memo using named function expression pattern
- Both components have displayName set for React DevTools visibility
- Syntax checks pass for both files
- Components will skip re-renders when props are shallowly equal (verifiable with DevTools)
</success_criteria>
<output>
After completion, create `.planning/phases/30-component-memoization/30-01-SUMMARY.md`
</output>