Skip to main content

Routing

FrontHub enables that you use routers inside your micro frontend environment. It is possible to use routers even though the application host has more than one micro frontend application running at the same time on the same page.

To do that FrontHub uses, configures react-router-dom library and provides custom hooks in a way it can manage page transitions safely.

To start using a router in your micro frontend, just install react-router-dom and use it.

 yarn add react-router-dom
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route } from 'react-router-dom'
import { useHistory } from '@resultadosdigitais/front-hub/react'

// All route props (match, location and history) are available to User
function User(props) {
return <h1>Hello {props.match.params.username}!</h1>
}

ReactDOM.render(
<Router history={history}>
<Route path="/user/:username" component={User} />
</Router>,
node,
)

History Hook

Beginning with version 9, Fronthub introduces a custom history hook designed to enhance, enable single-page application (SPA) navigation within shell applications, ensures smooth navigation transitions between micro frontends and eliminates issues that may arise when navigating between them. All micro frontends using Router functionality will need to utilize this hook. Fronthub will coordinate all micro frontends with a single Router, ensuring seamless navigation between micro frontends embedded within one another.

Using with Router

import { useHistory } from '@resultadosdigitais/front-hub/react'
import { Router, Route } from 'react-router-dom'

const Routes = () => {
const history = useHistory()

return (
<Router history={history}>
<Route path="/user/:username" component={User} />
<Route path="/dashboard" component={Dashboard} />
</Router>
)
}

Basename

Starting from version 9, Fronthub no longer supports the basename property from react-router-dom. Instead, it is necessary to manually add the route basename to each route.

Before:

return (
<Router basename="/app/settings/imports">
<Switch>
<Route path="/" exact>
<EmptyState />
</Route>
<Route path="/dados-gerais" exact>
<GeneralData />
</Route>
</Switch>
</Router>
)

Now:

const basename = '/app/settings/imports'

return (
<Router>
<Switch>
<Route path=`${basename/}` exact>
<EmptyState />
</Route>
<Route path=`${basename/dados-gerais}` exact>
<GeneralData />
</Route>
</Switch>
</Router>
)

SPA Routes and Application Host Configuration

For the microfrontend to be able to control the route, it must be passed on by the Application Host. This means that the route configuration on the backend will need to be done in a way that makes your SPA be rendered by the application host for all the routes that the microfrontend has. There are two ways to do this is by using a route with a wildcard

For example, consider an SPA with the following routes and components:

  • /users - Component: UserListPage
  • /users/new - Component: UserFormPage
  • /users/:userId - Component: UserDetailPage
  • /users/:userId/groups - Component: UserGroupPage

The SPA routing configuration code is as follows:

<Router history={history}>
<Switch>
<Route path={'/users/'} exact>
<UserListPage />
</Route>
<Route path={'/users/new'} exact>
<UserFormPage />
</Route>
<Route path={'/users/:userId'} exact>
<UserDetailPage />
</Route>
<Route path={'/users/:userId/groups'} exact>
<UserGroupPage />
</Route>
</Switch>
</Router>

Rendering with a Wildcard route - Ruby On Rails example

Using a wildcard can simplify the routing configuration. The routes.rb would look something like the following:

get 'users/*', to: 'users#index'

By using a wildcard, you only need to add one method on the controller to respond to all routes:


class UsersController < SessionProtectedController

def index
render 'users/frontend/index'
end

end

How to navigate

Due to the implementation of the new shared history and the navigation between micro frontends using the new component, it will be necessary to adjust the navigation approach from what is commonly used in a few micro frontends.

With useHistory hook (all history properties are available like in the react router documentation)

import { useHistory } from '@resultadosdigitais/front-hub/react'
import { Button } from '@resultadosdigitais/tangram-components'
///...other_imports

const YourComponent = () => {
const history = useHistory()

const handleRedirect = () => {
///...do_something
history.push('/the_route')
}

return (
<div>
<Button onClick={handleRedirect}>Redirect</Button>
</div>
)
}
import { Link } from 'react-router-dom'
...other_imports

const YourComponent = () => {
return <Link to="/my-path">Hello</Link>
}
import { Link as LinkRouter } from 'react-router-dom'
import { Link } from '@resultadosdigitais/tangram-components'

export default function ExampleMyComponent() {
return (
<Link to="/my-path" as={LinkRouter}>
Hello
</Link>
)
}

You may consult the library documentation if you have any questions on how to use it.

As a side note, we do not support "state" property as it is a common source of bugs and as implemented today do not allow the end user to share urls.

You can read more information about it on the proposal Draft Frontend Architecture