From be62c5d43ec6ce681ee04505afbc39096f470e73 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 5 May 2026 05:04:40 +0000 Subject: [PATCH] fix(playground): stabilize onQueryChange callback to prevent stale closures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The onQueryChange callback in useQueryBuilder was captured in a useEffect closure but not included in the dependency array. When the parent component provided a new callback (e.g. after creating a new exploration or switching reports in the IDE), the stale callback would be called instead. This caused report creation in the IDE to appear to succeed (the chart renders because the data query works) while the save callback — provided by the parent — was stale and pointed to the wrong context. Fix: wrap onQueryChange with useEvent (already available in the codebase) to ensure the latest callback is always invoked without adding it to the useEffect dependency array (which would cause unnecessary re-fires). Co-authored-by: Artyom Keydunov --- .../src/QueryBuilderV2/hooks/query-builder.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/cubejs-playground/src/QueryBuilderV2/hooks/query-builder.ts b/packages/cubejs-playground/src/QueryBuilderV2/hooks/query-builder.ts index 579ad522bd792..0f7a879c051c9 100644 --- a/packages/cubejs-playground/src/QueryBuilderV2/hooks/query-builder.ts +++ b/packages/cubejs-playground/src/QueryBuilderV2/hooks/query-builder.ts @@ -129,6 +129,10 @@ export function useQueryBuilder(props: UseQueryBuilderProps) { onQueryChange, } = props; + const onQueryChangeStable = useEvent((...args: Parameters>) => { + onQueryChange?.(...args); + }); + function queryValidation(query: Query) { let validatedQuery = validateQuery(query); @@ -1024,7 +1028,7 @@ export function useQueryBuilder(props: UseQueryBuilderProps) { }, [queryHash, chartType, meta]); useEffect(() => { - onQueryChange?.({ query, chartType, pivotConfig }); + onQueryChangeStable({ query, chartType, pivotConfig }); }, [queryHash, chartType, pivotConfig]); // Update invalidation markers