From da85da1ab319de236d2bfb1fb324fea6afe6e969 Mon Sep 17 00:00:00 2001 From: Mikael Grankvist Date: Tue, 12 Nov 2024 08:56:56 +0200 Subject: [PATCH] fix: multiple fast navigate calls Fix issue where a slow connection and fast `navigate` calls throws exception due to faulty blocker state change. Fixes #20404 --- .../resources/com/vaadin/flow/server/frontend/Flow.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx index e3e571470c3..4066b940d2a 100644 --- a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx +++ b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/Flow.tsx @@ -273,6 +273,7 @@ function Flow() { }); const location = useLocation(); const navigated = useRef(false); + const blockerHandled = useRef(false); const fromAnchor = useRef(false); const containerRef = useRef(undefined); const roundTrip = useRef | undefined>(undefined); @@ -360,9 +361,18 @@ function Flow() { }, []); useEffect(() => { + if(blockerHandled.current) { + // blocker is handled and no new navigation is accepted. + // This will cancel multiple navigate calls, but not multiple calls + // from the server as those are queued. #20404 + return; + } if (blocker.state === 'blocked') { + blockerHandled.current = true; let blockingPromise: any; roundTrip.current = new Promise((resolve,reject) => blockingPromise = {resolve:resolve,reject:reject}); + // Release blocker handling after promise is fulfilled + roundTrip.current.then(() => blockerHandled.current = false, () => blockerHandled.current = false); // Proceed to the blocked location, unless the navigation originates from a click on a link. // In that case continue with function execution and perform a server round-trip