router icon indicating copy to clipboard operation
router copied to clipboard

Hook to define how to react to route changes

Open bennypowers opened this issue 4 years ago • 2 comments

Hello!

Problem Case

Say our app is using vaadin-router for routing, and apollo-client for state management.

All the app's state except routing information is managed by apollo, all the routing info is managed by vaadin.

In this scenario, let's imagine a <user-profile> component, which is rendered by the routing table at some route /users/:userId:

import { ApolloQuery, property } from '@apollo-elements/lit-apollo';
import type { RouterLocation } from '@vaadin/router/dist/vaadin-router';
import UserQuery from './User.query.graphql'; // let's say 

export class UserProfile extends ApolloQuery {
  // connect to the state-store
  query = UserQuery;
  
  // receive routing updates.
  @property({ attribute: false }) location: RouterLocation;
  
  // define query variables for use in connecting to the state store
  get variables() {
    return {
      userId: this.location?.params.userId as string;
    }
  }
}

In this arrangement, we've tightly coupled the state store, the component, and the routing table. We can help a little by making the location property declaration a mixin prop, and maybe also the variables getter, depending on the use case, but it's still highly coupled.

This breaks down when attempting to use the component outside of it's app (i.e. routing-table) context, for example in storybook:

import { html, text, withKnobs } from '@open-wc/demoing-storybook';

export const UserPage = () => html`
  <user-profile .location="${ params: { userId: text('User Id', 'default-id') } }"></user-profile>
`;

This makes for an awkward storybook setup, and furthermore, when storybook changes the preview iframe's url, our knob settings will be overwritten.

Proposed Solution

I propose exposing a hook on the Router object which determines what to do to components when the route changes. The default hook would assign location as it currently does, but users could customize that behaviour, both at the top level, and per route (i.e. in child routes), for example, by setting some well-known attribute like user-id on the rendered elements.

This would allow users to factor components which take properties of their choosing, disable routing for cases which do not require them (like storybook, or micro-frontends outside of an app context).

Thanks for your consideration.

bennypowers avatar Jun 03 '20 07:06 bennypowers

Thank you @bennypowers for your ticket, very interesting case and proposal. We are currently focusing on a new Vaadin release, and We cannot spare resources on router. Once we get that done, we will see what to do with your proposal and let you know. Sorry for keeping you waiting, and thanks for your patience.

haijian-vaadin avatar Jun 05 '20 20:06 haijian-vaadin

👍 Ok looking forward to hearing back.

In the mean time if it becomes pressing and I develop a patch, I'll be sure to upstream the PR (no promises though)

bennypowers avatar Jun 06 '20 17:06 bennypowers