-
Notifications
You must be signed in to change notification settings - Fork 0
⚡ Bolt: Defer expensive rubric calculations during text streaming #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ## 2024-05-27 - UI Blocking During Text Streaming | ||
| **Learning:** During simulated text generation loops (like `setInterval` firing every 24ms), synchronous deterministic scoring and analysis functions that depend on the rapidly updating text state can bottleneck the main thread, leading to jittery render loops or missed frames. | ||
| **Action:** Use React's `useDeferredValue` for rapidly updating text state before passing it into complex computations (like `analyzeText` or `scoreDeterministic` in `useMemo`). This allows React to process the updates asynchronously and interruptibly, maintaining UI responsiveness during simulated text streaming. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; | ||
| import { AnimatePresence, motion } from "framer-motion"; | ||
| import { useEffect, useMemo, useRef, useState } from "react"; | ||
| import { useDeferredValue, useEffect, useMemo, useRef, useState } from "react"; | ||
| import { USE_CASE_PRESETS } from "../../src/lib/presets"; | ||
| import { analyzeText, scoreDeterministic } from "../../src/lib/rubric"; | ||
| import type { Guide, UseCase } from "../../src/lib/types"; | ||
|
|
@@ -255,7 +255,11 @@ export function PlaygroundView({ | |
| }; | ||
| }, [output]); | ||
|
|
||
| const snapshot = useMemo(() => analyzeText(visibleOutput), [visibleOutput]); | ||
| // Defer the expensive analyzeText and scoreDeterministic calculations to a lower | ||
| // priority render cycle. This prevents them from blocking the main UI thread during | ||
| // rapid state updates like text streaming (which happens every 24ms). | ||
| const deferredOutput = useDeferredValue(visibleOutput); | ||
| const snapshot = useMemo(() => analyzeText(deferredOutput), [deferredOutput]); | ||
|
Comment on lines
+261
to
+262
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because the rubric is still rendered whenever Useful? React with 👍 / 👎. |
||
| const { score, details } = useMemo( | ||
| () => | ||
| guide | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When using
useDeferredValueto defer expensive computations during rapid state updates (like text streaming), the UI can display a temporary mismatch between the latest streamed text (visibleOutput) and the deferred analysis results (snapshot,score).To prevent user confusion, it is a recommended UX best practice to visually indicate when the deferred calculations are stale (out-of-sync with the current text). You can derive this state by comparing the current and deferred values, and then use it to apply a visual treatment (such as reducing the opacity of the
<RubricSnapshot />container or showing a subtle loading indicator) while the background calculation is pending.