Spaces:
Running
Fix code streaming: Use functional state updates in React
Browse filesIssue: Code only appeared at the end instead of streaming in real-time
Root cause: React state updates were using a stale closure over the buffer variable
Fix:
- Replace buffer variable with functional state updates: setGeneratedCode(prev => prev + chunk)
- This ensures each update works with the latest state, not stale closure
- Clear previous code before starting new generation
- Improved logging to show total code length as it grows
How it works now:
1. Clear code editor when starting generation
2. Each chunk calls setGeneratedCode with functional update
3. React always appends to latest state, not stale buffer
4. Console logs show: 'Received chunk' and 'Total code length' growing
5. Monaco editor updates immediately as code grows
This ensures true streaming where users see code appear character by character
as the LLM generates it, not all at once at the end.
- frontend/src/app/page.tsx +10 -5
|
@@ -51,6 +51,9 @@ export default function Home() {
|
|
| 51 |
};
|
| 52 |
setMessages((prev) => [...prev, userMessage]);
|
| 53 |
setIsGenerating(true);
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
// Prepare request
|
| 56 |
const request: CodeGenerationRequest = {
|
|
@@ -62,7 +65,6 @@ export default function Home() {
|
|
| 62 |
agent_mode: false,
|
| 63 |
};
|
| 64 |
|
| 65 |
-
let generatedCodeBuffer = '';
|
| 66 |
const assistantMessage: Message = {
|
| 67 |
role: 'assistant',
|
| 68 |
content: '⏳ Generating code...',
|
|
@@ -76,12 +78,15 @@ export default function Home() {
|
|
| 76 |
try {
|
| 77 |
apiClient.generateCodeStream(
|
| 78 |
request,
|
| 79 |
-
// onChunk - Update code editor in real-time
|
| 80 |
(chunk: string) => {
|
| 81 |
-
generatedCodeBuffer += chunk;
|
| 82 |
console.log('[Stream] Received chunk:', chunk.substring(0, 50), '... (length:', chunk.length, ')');
|
| 83 |
-
|
| 84 |
-
setGeneratedCode(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
},
|
| 86 |
// onComplete
|
| 87 |
(code: string) => {
|
|
|
|
| 51 |
};
|
| 52 |
setMessages((prev) => [...prev, userMessage]);
|
| 53 |
setIsGenerating(true);
|
| 54 |
+
|
| 55 |
+
// Clear previous code to show streaming from start
|
| 56 |
+
setGeneratedCode('');
|
| 57 |
|
| 58 |
// Prepare request
|
| 59 |
const request: CodeGenerationRequest = {
|
|
|
|
| 65 |
agent_mode: false,
|
| 66 |
};
|
| 67 |
|
|
|
|
| 68 |
const assistantMessage: Message = {
|
| 69 |
role: 'assistant',
|
| 70 |
content: '⏳ Generating code...',
|
|
|
|
| 78 |
try {
|
| 79 |
apiClient.generateCodeStream(
|
| 80 |
request,
|
| 81 |
+
// onChunk - Update code editor in real-time
|
| 82 |
(chunk: string) => {
|
|
|
|
| 83 |
console.log('[Stream] Received chunk:', chunk.substring(0, 50), '... (length:', chunk.length, ')');
|
| 84 |
+
// Use functional update to ensure we always append to latest state
|
| 85 |
+
setGeneratedCode((prevCode) => {
|
| 86 |
+
const newCode = prevCode + chunk;
|
| 87 |
+
console.log('[Stream] Total code length:', newCode.length);
|
| 88 |
+
return newCode;
|
| 89 |
+
});
|
| 90 |
},
|
| 91 |
// onComplete
|
| 92 |
(code: string) => {
|