in issue-tracker/src/routing/createRouter.js [10:71]
export default function createRouter(routes, options) {
// Initialize history
const history = createBrowserHistory(options);
// Find the initial match and prepare it
const initialMatches = matchRoute(routes, history.location);
const initialEntries = prepareMatches(initialMatches);
let currentEntry = {
location: history.location,
entries: initialEntries,
};
// maintain a set of subscribers to the active entry
let nextId = 0;
const subscribers = new Map();
// Listen for location changes, match to the route entry, prepare the entry,
// and notify subscribers. Note that this pattern ensures that data-loading
// occurs *outside* of - and *before* - rendering.
const cleanup = history.listen((location, action) => {
if (location.pathname === currentEntry.location.pathname) {
return;
}
const matches = matchRoute(routes, location);
const entries = prepareMatches(matches);
const nextEntry = {
location,
entries,
};
currentEntry = nextEntry;
subscribers.forEach(cb => cb(nextEntry));
});
// The actual object that will be passed on the RoutingConext.
const context = {
history,
get() {
return currentEntry;
},
preloadCode(pathname) {
// preload just the code for a route, without storing the result
const matches = matchRoutes(routes, pathname);
matches.forEach(({ route }) => route.component.load());
},
preload(pathname) {
// preload the code and data for a route, without storing the result
const matches = matchRoutes(routes, pathname);
prepareMatches(matches);
},
subscribe(cb) {
const id = nextId++;
const dispose = () => {
subscribers.delete(id);
};
subscribers.set(id, cb);
return dispose;
},
};
// Return both the context object and a cleanup function
return { cleanup, context };
}