platform
platform copied to clipboard
React hybrid routing
Description
Support routing to Flow views in React+Hilla applications using React Router.
Use cases
As a developer
I want to extend my React+Hilla application with server-side Flow views
So that I can benefit from Flow provided features, e.g. server-side navigation, Push and others.
As a developer
I want to extend my Flow application with React-based views/components using Hilla
So that I can benefit from using React where I want.
Acceptance criteria
- [x] React Router is integrated with the client-side and server-side Flow API in a same way as Vaadin Router does for Lit -
@ClientCallable
and methods inFlow.js
, so that this integration doesn't bring major changes in Flow API. - [x] Flow automatically generates on a build phase the codes for
App.tsx
androutes.tsx
that is needed to connect React Router with the Flow API - [x] Flow views are rendered inside the same client-side main layout that is used for existing Hilla views.
- [x] Adding Flow routes to React+Hilla apps need minor manual route customisation, which is well-documented in Hilla/Flow docs.
- [x] The integration supports the same routing features as the Vaadin Router integration with regards to e.g.
- [x] access control, including rerouting to a login page
- [x] navigation events and server-side navigation
- [x] beforeLeaveEvent.postpone()
- [x] handling context path and query parameter within navigation
- [x] routing exception handling
- [x] page titles
- [x] RouterLink and Anchor works the same way as for Vaadin Router
- [x] Push support
- [x] MPR
- [x] eager bootstrapping/rendering.
General criteria
- Flow applications that are not hybrids keep using Vaadin Router just like today.
- No need for a new routing API for Hilla, this isn't in scope of this project.
- This acceptance criteria covers the routing aspect of integration between Flow and React. Other aspects such as reusing 3rd party React components or using React as a template language from Flow are outside the scope of this project.
- React router integration is turned on by feature flag and Flow gives a clarification message to developer about the need of adding this feature flag.
- Flow tracks usage of hybrid configuration, including React+Hilla+Flow, Lit+Hilla+Flow cases.
- start.vaadin.com includes starter project for React+Hilla+Flow, having Hilla and Flow views and feature flag turned ON by default.
- [ ] APIs reviewed
- [ ] Design
- [ ] Performance
- [ ] UX/DX tests in Alpha
- [ ] Documentation:
- [ ] How to test?
- [ ] Limitations:
Security
- [ ] Security implications have been taken into account (elaborate or link to product security requirement specification if there are implications)
navigation events and server-side navigation
Tested Hilla view -> Flow view navigation and navigation lifecycle events: BeforeLeaveEvent
, BeforeEnterEvent
, AfterNavigationEvent
, including .addBeforeEnterListener()
listener and forwardTo/rerouteTo
methods. Works as expected.
Minimal documentation on getting the combination to work
Adding Flow to a Hilla-react project. (sample from CRM tutorial)
- Add the flow managed dependency bom to pom.xml
<properties>
<java.version>17</java.version>
<vaadin.version>24.3-SNAPSHOT</vaadin.version>
<hilla.version>2.4.0</hilla.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<version>${vaadin.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Other pom imports like hilla -->
</dependencies>
</dependencyManagement>
-
Add the vaadin-core / vaadin dependency
<dependency> <groupId>com.vaadin</groupId> <!-- Replace artifactId with vaadin-core to use only free components --> <artifactId>vaadin</artifactId> </dependency>
-
enable in
src/main/resources/vaadin-featureflags.properties
react for flow with:com.vaadin.experimental.reactRouter=true
-
Into
frontend/routes.tsx
add the serverSideRoutes object:mport {serverSideRoutes} from "Frontend/generated/flow/Flow"; .. xport const routes = [ // Hilla definitions ...serverSideRoutes
.crm_routes
xport const routes = [ { element: <MainLayout />, handle: { title: 'Hilla CRM' }, children: [ { path: '/', element: <ContactsView />, handle: { title: 'Contacts' } }, { path: '/about', element: <AboutView />, handle: { title: 'About' } }, ...serverSideRoutes ], }, as RouteObject[];
[NOTE] The
Frontend/generated/flow/Flow
will be created when the project is run (node tasks will generate this) -
Add Flow views with Route annotation.
-
Run project and Flow views can be navigated to.
Enabling eagerServerLoad
in a Flow project works as expected. Also couldn't see any issues in a hilla-flow-react hybrid after enabling the flag.
Access control seems to work fine for Flow view.
- Navigating from Hilla view to protected Flow view reroutes to login view if not authenticated.
- Navigating from Hilla view to unauthorised Flow view shows "Could not navigate to..." standard page.
However, one thing that doesn't work is navigating to Hilla view that is protected by a role. For some reason, this view redirects back to login view, even after successful login. Public Hilla view doesn't have this problem.
In the browser console log I see that UserInfoService returns "ROLE_USER" to the client and login method returns no errors.
Maybe my project configuration is incorrect. I followed this tutorial https://hilla.dev/docs/react/guides/security/spring-login.
Here is my test project. proto-hilla-react-hybrid.zip
@platosha could you please verify my test project when appropriate ?
- Add hilla managed dependency bom to pom.xml
<properties>
...
<hilla.version>2.3.3</hilla.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Other pom imports like hilla -->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla-bom</artifactId>
<version>${hilla.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
- Add hilla-react and hilla-spring-boot-starter dependencies
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla-react</artifactId>
</dependency>
<!-- REPLACE vaadin-spring-boot-starter with hilla starter
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-boot-starter</artifactId>
</dependency>-->
<dependency>
<groupId>dev.hilla</groupId>
<artifactId>hilla-react-spring-boot-starter</artifactId>
</dependency>
- Change all vaadin-maven-plugin instances into hilla-maven-plugin
<plugin>
- <groupId>com.vaadin</groupId>
- <artifactId>vaadin-maven-plugin</artifactId>
- <version>${vaadin.version}</version>
+ <groupId>dev.hilla</groupId>
+ <artifactId>hilla-maven-plugin</artifactId>
+ <version>${hilla.version}</version>
<executions>
<execution>
<goals>
- enable in src/main/resources/vaadin-featureflags.properties react for flow with:
com.vaadin.experimental.reactRouter=true
-
Run
mvn hilla:init-app
-
Add into frontend/routes.tsx the serverSideRoutes object:
import {serverSideRoutes} from "Frontend/generated/flow/Flow";
...
export const routes = [
// Hilla definitions
...serverSideRoutes
]
So the issue with React routes redirect was that the server returns {"authorities": ["ROLE_USER"]}
, whereas the Hilla helper expects {"roles": ["USER"]}
. This implementation mismatch is not related with hybrid routing and is easy to workaround by specifying client-side auth configuration with getRoles
.
This ticket/PR has been released with Vaadin 24.4.0.