You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While investigating the animated dialogue scenes used in the A2 English for Developers curriculum, I noticed that the Scene component appears to continuously rerender during playback because animation progress is being tracked through React state updates inside a requestAnimationFrame loop.
After profiling and instrumenting the components locally, it looks like these parent rerenders propagate into the Character subtree even when most character props remain unchanged.
Verification
I added temporary instrumentation using:
console.count('Scene render');
console.count('Character render');
and also logged Character props during playback.
I then profiled the scene playback using React DevTools Profiler.
During playback:
Scene rerenders continuously throughout the animation
all Character components rerender repeatedly
profiler recorded a very large number of commits during a short playback session
many rerenders occurred even when character props stayed identical
Example observations from logged props:
{ name: 'Alice', isTalking: false, opacity: 1, position: { x: ..., y: ..., z: ... }}
The same values were repeatedly logged across many renders.
Suspected Render Flow
requestAnimationFrame→ setCurrentTime(...)→ Scene rerender→ Character subtree rerender
The likely trigger seems to be:
setCurrentTime(time);
inside the animation loop in scene.tsx.
Additional Validation
I temporarily wrapped Character with:
React.memo(Character)
After doing this:
Character rerenders dropped significantly
rerenders became more closely tied to actual prop changes (isTalking, etc.)
Scene itself still rerendered heavily, but subtree churn reduced substantially
This suggests that a meaningful portion of the rerenders may currently be avoidable.
Potential Impact
This may cause:
unnecessary reconciliation work
extra CPU usage during playback
reduced smoothness on lower-end devices
unnecessary rerender propagation across scene children
I have not opened a PR yet because I wanted to first confirm whether this behavior is expected and whether maintainers would prefer:
localized memoization boundaries
render isolation
or a larger timeline/update refactor approach.
While investigating the animated dialogue scenes used in the A2 English for Developers curriculum, I noticed that the Scene component appears to continuously rerender during playback because animation progress is being tracked through React state updates inside a requestAnimationFrame loop.
After profiling and instrumenting the components locally, it looks like these parent rerenders propagate into the Character subtree even when most character props remain unchanged.
Files Involved
client/src/templates/Challenges/components/scene/scene.tsx
client/src/templates/Challenges/components/scene/character.tsx
Verification
I added temporary instrumentation using:
console.count('Scene render');
console.count('Character render');
and also logged Character props during playback.
I then profiled the scene playback using React DevTools Profiler.
During playback:
Scene rerenders continuously throughout the animation
all Character components rerender repeatedly
profiler recorded a very large number of commits during a short playback session
many rerenders occurred even when character props stayed identical
Example observations from logged props:
{ name: 'Alice', isTalking: false, opacity: 1, position: { x: ..., y: ..., z: ... }}
The same values were repeatedly logged across many renders.
Suspected Render Flow
requestAnimationFrame→ setCurrentTime(...)→ Scene rerender→ Character subtree rerender
The likely trigger seems to be:
setCurrentTime(time);
inside the animation loop in scene.tsx.
Additional Validation
I temporarily wrapped Character with:
React.memo(Character)
After doing this:
Character rerenders dropped significantly
rerenders became more closely tied to actual prop changes (isTalking, etc.)
Scene itself still rerendered heavily, but subtree churn reduced substantially
This suggests that a meaningful portion of the rerenders may currently be avoidable.
Potential Impact
This may cause:
unnecessary reconciliation work
extra CPU usage during playback
reduced smoothness on lower-end devices
unnecessary rerender propagation across scene children
I have not opened a PR yet because I wanted to first confirm whether this behavior is expected and whether maintainers would prefer:
localized memoization boundaries
render isolation
or a larger timeline/update refactor approach.
Attachments
React Profiler flamegraph screenshot
and
React Profiler commit timeline screenshot
Console render spam screenshot
Screen.Recording.2026-05-11.at.13.17.10.mov
Console logs showing stable Character props
Screen.Recording.2026-05-11.at.13.42.16.mov