codeant-ai-for-open-source[bot] commented on code in PR #42473:
URL: https://github.com/apache/superset/pull/42473#discussion_r3664354777


##########
superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:
##########
@@ -227,7 +235,20 @@ const updateHistory = debounce(
           force,
           false,
         );
-        history.replace(url, payload);
+        const previousChartState = getChartStateFromHistoryState(
+          history.location.state,
+        );
+        const state = toChartStateHistoryState(payload, sliceId);
+        if (
+          isReplace ||
+          !previousChartState ||
+          isEqual(previousChartState, getChartStateFromHistoryState(state))
+        ) {
+          history.replace(url, state);
+        } else {
+          // one entry per chart state is what makes the Back button undo it
+          history.push(url, state);
+        }

Review Comment:
   **Suggestion:** The debounced callback reads `history.location` only when it 
finally executes, so a query initiated on chart A can run after navigation to 
chart B and then push or replace chart A's form data into B's current Explore 
route. The pathname check does not establish that the route still represents 
the same chart. Capture the originating location/chart identity and discard the 
delayed update when it no longer matches. [race condition]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Chart B history can receive chart A state.
   - ❌ Explore URLs may point to the wrong chart.
   - ⚠️ POP navigation can mix states across charts.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Edit chart A and trigger `addHistory()` through `reRenderChart()` at
   
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:618-631`;
   `updateHistory` is debounced for 1000ms at
   
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:172-258`.
   
   2. Navigate to chart B in Explore before the debounced callback executes, or 
while its
   `postFormData`/`putFormData` request is awaiting completion at
   
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:225-237`.
   
   3. The callback still receives chart A's captured `formData`, but reads the 
shared
   `history.location` only after the await at
   
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:238-241`.
 Its
   only route guard, `pathname.startsWith('/explore')` at lines 227-229, 
remains true for
   chart B.
   
   4. The callback then pushes or replaces chart A's URL and chart-state 
payload into the
   current chart B history entry at
   
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:242-251`.
   Subsequent POP handling can reload or restore the wrong chart state.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=46e46a656d8d4653bcb741ca7ce44e59&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=46e46a656d8d4653bcb741ca7ce44e59&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/explore/components/ExploreViewContainer/index.tsx
   **Line:** 238:251
   **Comment:**
        *Race Condition: The debounced callback reads `history.location` only 
when it finally executes, so a query initiated on chart A can run after 
navigation to chart B and then push or replace chart A's form data into B's 
current Explore route. The pathname check does not establish that the route 
still represents the same chart. Capture the originating location/chart 
identity and discard the delayed update when it no longer matches.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42473&comment_hash=13d8cf0f9f0d3e86838105e4648067019f8f5bccebe696b52fffe955cbd6d479&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42473&comment_hash=13d8cf0f9f0d3e86838105e4648067019f8f5bccebe696b52fffe955cbd6d479&reaction=dislike'>👎</a>



##########
superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:
##########
@@ -611,6 +639,32 @@ function ExploreViewContainer(props: 
ExploreViewContainerProps) {
     ],
   );
 
+  // Explore's own entries carry the chart state they were pushed with, so a 
POP
+  // into one is an undo/redo: apply it and re-query in place, which is also 
why
+  // ExplorePage skips its reload for them.
+  const sliceId = props.form_data.slice_id ?? props.slice?.slice_id;
+  const { datasource: datasourceUid } = props.form_data;
+  useEffect(
+    () =>
+      history.listen((loc: Location, action: Action) => {
+        const chartState = getChartStateFromHistoryState(loc.state);
+        if (
+          action !== 'POP' ||
+          !chartState ||
+          !isSameChartState(chartState, {
+            slice_id: sliceId,
+            datasource: datasourceUid,
+          })
+        ) {
+          return;
+        }
+        restoringFromHistory.current = true;
+        props.actions.setExploreControls(chartState);
+        props.actions.triggerQuery(true, props.chart.id);

Review Comment:
   **Suggestion:** `setExploreControls` only updates the explore controls; it 
does not update `form_data`, while the chart query path invoked by 
`triggerQuery` posts the existing `formData` prop. Therefore a POP restore 
immediately queries using the prior chart state rather than the popped state, 
and the stale `form_data` also remains available to subsequent history updates. 
Restore the complete form-data state or explicitly build and post the query 
from `chartState` after the controls have been applied. [incomplete 
implementation]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Explore Back restores controls but queries stale form data.
   - ❌ Chart results can disagree with displayed control values.
   - ⚠️ Subsequent history entries retain stale form-data state.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open a saved chart in Explore and create multiple history states through 
the query path
   at 
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:618-631`,
   which stores the changed form data in each history entry.
   
   2. Press Back to a same-chart entry; the POP listener at
   
`superset-frontend/src/explore/components/ExploreViewContainer/index.tsx:649-664`
 calls
   `setExploreControls(chartState)` and then `triggerQuery(true, 
props.chart.id)`.
   
   3. `setExploreControls()` only dispatches `SET_EXPLORE_CONTROLS` at
   `superset-frontend/src/explore/actions/exploreActions.ts:105-108`; the 
reducer updates
   only `controls` at 
`superset-frontend/src/explore/reducers/exploreReducer.ts:537-545` and
   leaves `form_data` unchanged.
   
   4. `triggerQuery()` only toggles the chart trigger flag at
   `superset-frontend/src/components/Chart/chartAction.ts:661-665`. The 
resulting `Chart`
   query calls `postChartFormData(formData, ...)` using its existing `formData` 
prop at
   `superset-frontend/src/components/Chart/Chart.tsx:229-245`, so the request 
posts the
   pre-POP form data instead of `chartState`. The visible controls and queried 
data can
   therefore diverge, and later history updates continue using stale 
`props.form_data`.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=baaebc34cba546c69542712219477f2a&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=baaebc34cba546c69542712219477f2a&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/explore/components/ExploreViewContainer/index.tsx
   **Line:** 661:663
   **Comment:**
        *Incomplete Implementation: `setExploreControls` only updates the 
explore controls; it does not update `form_data`, while the chart query path 
invoked by `triggerQuery` posts the existing `formData` prop. Therefore a POP 
restore immediately queries using the prior chart state rather than the popped 
state, and the stale `form_data` also remains available to subsequent history 
updates. Restore the complete form-data state or explicitly build and post the 
query from `chartState` after the controls have been applied.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42473&comment_hash=9947231ed3837632ef8589d0523ebcb6ace86bf9614645e60bc6256f85df0f67&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F42473&comment_hash=9947231ed3837632ef8589d0523ebcb6ace86bf9614645e60bc6256f85df0f67&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to