fix(studio): AIPanel onDone 改用 ref 读流式正文,消除渲染期跨组件 setState
AIPanel onDone 此前在 setStreamContent 更新函数里调父组件 onCandidateGenerated→AIPanel 渲染期触发 WorkspacePage setState(React warn "Cannot update a component while rendering a different component")。改:streamContentRef 在 onChunk 与 streamContent 同步累计,onDone 直接读 ref 调回调,不再渲染期 setState。ai-generation e2e 再跑 React warning grep=0(消失)、仍 passed(26.2s)。顺带修 AgentPage.contract.test 多余 import React(JSX automatic runtime 不需→TS6133;此前写 test 只跑 vitest 漏跑 tsc、commit 4c069d4 带入)。tsc 全量 0、vitest 102/102。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
494c9e9b89
commit
410322cbc0
@ -42,6 +42,10 @@ export default function AIPanel({
|
||||
|
||||
// 维护中止控制器的引用以管理流生命周期
|
||||
const abortControllerRef = React.useRef<AbortController | null>(null);
|
||||
// 流式正文最新值镜像:onDone 需读累计正文回传上层。用 ref 而非在 setStreamContent 更新函数里调父组件回调——
|
||||
// 后者会在 AIPanel 渲染期触发 WorkspacePage setState(React 警告 "Cannot update a component while rendering
|
||||
// a different component")。ref 与 streamContent 在 onChunk 同步累计,onDone 直接读 ref 即为最新值。
|
||||
const streamContentRef = React.useRef('');
|
||||
|
||||
// 1. 发起 AI 生成请求
|
||||
const handleGenerate = async () => {
|
||||
@ -54,6 +58,7 @@ export default function AIPanel({
|
||||
|
||||
setIsGenerating(true);
|
||||
setStreamContent('');
|
||||
streamContentRef.current = '';
|
||||
setErrorMsg('');
|
||||
|
||||
try {
|
||||
@ -82,6 +87,7 @@ export default function AIPanel({
|
||||
|
||||
const controller = connectAIStream(`/app-api/muse/ai/tasks/${task.taskId}/stream`, {
|
||||
onChunk: (data) => {
|
||||
streamContentRef.current += data.content;
|
||||
setStreamContent((prev) => prev + data.content);
|
||||
},
|
||||
onDone: (data) => {
|
||||
@ -90,10 +96,9 @@ export default function AIPanel({
|
||||
// 缺失时回传 null(上层据此禁用采纳按钮,只允许预览)。
|
||||
const suggestionId = data?.suggestionId ?? null;
|
||||
// 通过回调将生成正文与候选 ID 一并提交给上层,以渲染候选 Diff 视图并支持采纳。
|
||||
setStreamContent((current) => {
|
||||
onCandidateGenerated(current, suggestionId);
|
||||
return current;
|
||||
});
|
||||
// 直接读 streamContentRef(onChunk 已同步累计),避免在 setStreamContent 更新函数里调父组件回调、
|
||||
// 在 AIPanel 渲染期触发 WorkspacePage 跨组件 setState。
|
||||
onCandidateGenerated(streamContentRef.current, suggestionId);
|
||||
abortControllerRef.current = null;
|
||||
},
|
||||
onError: (err) => {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { describe, expect, it, beforeEach } from 'vitest';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user