LWC - Best practice for routing?
There's a demo up on GitHub from the TDX session on using LWC outside of Salesforce.
That uses Navigo for routing in the app module. Here's a slimmed down version of the routing from that example with some comments from my own experience trying to implement this:
import { LightningElement, createElement, track } from 'lwc';
import Navigo from 'navigo'; // import Navigo
export default class App extends LightningElement {
// instantiate the router class
router = new Navigo(location.origin, false);
constructor() {
super();
// define your routes. The await functions are for use with chunking but you could remove them and just do a normal import if all of your scripts are loaded at once
this.router.on({
'/podcasts': async () => {
const { default: ViewPodcasts } = await import(/* webpackChunkName: "view-podcasts" */ 'view/podcasts');
this.setPage('view-podcasts', ViewPodcasts);
},
'/podcasts/:id': async ({ id }) => {
const { default: ViewPodcast } = await import(/* webpackChunkName: "view-podcast" */ 'view/podcast');
this.setPage('view-podcast', ViewPodcast, {
podcastId: parseInt(id, 10),
});
},
'/discover': async () => {
const { default: ViewDiscover } = await import(/* webpackChunkName: "view-discover" */ 'view/discover');
this.setPage('view-discover', ViewDiscover);
},
'/categories/:id': async ({ id }) => {
const { default: PodcastList } = await import(/* webpackChunkName: "view-category" */ 'view/category');
this.setPage('view-category', PodcastList, {
categoryId: parseInt(id, 10),
});
},
});
const navigateToDefault = () => {
this.router.navigate('/podcasts');
};
this.router.notFound(navigateToDefault);
this.router.on(navigateToDefault);
}
renderedCallback() {
// Resolve the current view only after the container has rendered
if (!this.isRendered) {
this.isRendered = true;
this.router.resolve();
}
}
setPage(tagName, component, props = {}) {
// when a route is called, create the related component and insert it into the DOM in whatever container you want
const el = createElement(tagName, {
is: component,
fallback: false,
});
Object.assign(el, props);
// Remove previous components from the container if necessary
const container = this.template.querySelector('.container');
while (container.firstChild) {
container.removeChild(container.firstChild);
}
container.appendChild(el);
}
}