docs(workspace): explain component state and async ownership

This commit is contained in:
2026-11-12 16:14:21 +08:00
parent cc2172319e
commit 65c54e7b9e
7 changed files with 19 additions and 1 deletions
@@ -23,6 +23,7 @@ const Renderers=createContext(defaultCanvasRenderers);
export function useCanvasRenderers(){return useContext(Renderers);}
/** extensions仅在useState惰性初始化时捕获;后续prop换引用不会热替换已打开项目的schema/renderer。 */
export function CanvasRuntimeHost({ children,extensions=[] }: { children: ReactNode;extensions?:readonly CanvasRuntimeExtension[] }) {
// 惰性初始化只装配对象/工厂,不在 render 直接打开项目;实际账户绑定和持久化租约由后续调用取得。
const [{host,renderers}] = useState(() => {
// 先组合内置与扩展模型,再按精确版本/结构验证renderer,冲突在打开项目之前失败。
const registry = createRegistry([...builtinComponents(),...extensions.flatMap(extension=>extension.components??[])]),renderers=createReactRenderers([...defaultCanvasRenderers.definitions,...extensions.flatMap(extension=>extension.renderers??[])],registry);
@@ -51,6 +52,7 @@ export function CanvasRuntimeHost({ children,extensions=[] }: { children: ReactN
* 真正卸载才发起host.close,保存失败由宿主错误回调/日志报告,不在此丢弃根或强行释放leader。 */
useEffect(() => {
const generation = ++lifetime.current;
// cleanup 不等待 close 完成,也不主动重试;异步失败经 host 的错误通道和此处 catch 报告。
// Strict Mode replays effects synchronously; only a real detach retires the host.
return () => { queueMicrotask(() => { if (lifetime.current === generation) void host.close().catch(error => console.error("[canvas-host]", error.message)); }); };
}, [host]);