---
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>
