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 5c9e29c1cb2..e3e571470c3 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 @@ -364,7 +364,8 @@ function Flow() { let blockingPromise: any; roundTrip.current = new Promise((resolve,reject) => blockingPromise = {resolve:resolve,reject:reject}); - // Do not skip server round-trip if navigation originates from a click on a link + // 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 if (navigated.current && !fromAnchor.current) { blocker.proceed(); blockingPromise.resolve(); @@ -421,6 +422,9 @@ function Flow() { }, [blocker.state, blocker.location]); useEffect(() => { + if (blocker.state === 'blocked') { + return; + } if (navigated.current) { navigated.current = false; fireNavigated(location.pathname,location.search); diff --git a/flow-tests/test-react-router/src/main/java/com/vaadin/flow/RouterLinkForwardingToParametersView.java b/flow-tests/test-react-router/src/main/java/com/vaadin/flow/RouterLinkForwardingToParametersView.java new file mode 100644 index 00000000000..cb36d4fc639 --- /dev/null +++ b/flow-tests/test-react-router/src/main/java/com/vaadin/flow/RouterLinkForwardingToParametersView.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2024 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.flow; + +import com.vaadin.flow.component.html.Div; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.router.RouterLink; + +@Route("com.vaadin.flow.RouterLinkForwardingToParametersView") +public class RouterLinkForwardingToParametersView extends Div { + + public RouterLinkForwardingToParametersView() { + RouterLink link = new RouterLink("Forwarding view", + ForwardingToParametersView.class); + link.setId("forwardViewLink"); + add(link); + } +} diff --git a/flow-tests/test-react-router/src/test/java/com/vaadin/flow/ForwardTargetIT.java b/flow-tests/test-react-router/src/test/java/com/vaadin/flow/ForwardTargetIT.java index 332462847c0..26ec242db6e 100644 --- a/flow-tests/test-react-router/src/test/java/com/vaadin/flow/ForwardTargetIT.java +++ b/flow-tests/test-react-router/src/test/java/com/vaadin/flow/ForwardTargetIT.java @@ -58,4 +58,27 @@ public void testSetParameterCalledOnlyOnceAfterForward() { .filter(span -> span.getText().equals("setParameter")) .count()); } + + // Test for https://github.com/vaadin/flow/issues/19822 + @Test + public void testRouterLinkSetParameterCalledOnlyOnceAfterForward() { + getDriver().get(getTestURL(getRootURL(), + "/view/com.vaadin.flow.RouterLinkForwardingToParametersView", + null)); + $("a").id("forwardViewLink").click(); + + try { + waitUntil(arg -> driver.getCurrentUrl().endsWith( + "/view/com.vaadin.flow.ForwardTargetWithParametersView")); + } catch (TimeoutException e) { + Assert.fail("URL wasn't updated to expected one: " + + "/view/com.vaadin.flow.ForwardTargetWithParametersView"); + } + + Assert.assertEquals("setParameter was called more than once", 1, + $(SpanElement.class).all().stream() + .filter(span -> span.getText().equals("setParameter")) + .count()); + } + }