nareshbhatia / mobx-state-router

MobX-powered router for React apps
https://nareshbhatia.github.io/mobx-state-router/
MIT License
227 stars 30 forks source link

Catch-all #65

Closed iexplore closed 5 years ago

iexplore commented 5 years ago

We are using MSR and are very happy with it but there is one thing I am wondering; Is there a possibility to have a catch-all (*) pattern to redirect to a general not-found page. Currently solved it like this: ... { name: 'errorPage', pattern: '/error', }, { name: 'notFound5', pattern: '/:notFound/:two/:three/:four/:five', beforeEnter: () => { throw new RouterState('notFound'); } }, { name: 'notFound4', pattern: '/:notFound/:two/:three/:four', beforeEnter: () => { throw new RouterState('notFound'); } }, { name: 'notFound3', pattern: '/:notFound/:two/:three', beforeEnter: () => { throw new RouterState('notFound'); } }, { name: 'notFound2', pattern: '/:notFound/:two', beforeEnter: () => { throw new RouterState('notFound'); } }, { name: 'notFound', pattern: '/:notFound', title: 'Page not found', message: "Back to the home page", beforeEnter: () => { throw new RouterState('errorPage', { title: 'page not found', message: 'Click here to go Back to the home page' }); } },

nareshbhatia commented 5 years ago

Hi @iexplore, glad to hear that you like mobx-state-router.

I am surprised that the router is not catching your unrecognized paths. Here's the code that does path matching (see history-adapter.ts)

        // Find the matching route
        const routes = this.routerStore.routes;
        let matchingRoute = null;
        let params = undefined;
        for (let i = 0; i < routes.length; i++) {
            const route = routes[i];
            params = matchUrl(location.pathname, route.pattern);
            if (params) {
                matchingRoute = route;
                break;
            }
        }

        if (matchingRoute) {
            return this.routerStore.goTo(
                new RouterState(
                    matchingRoute.name,
                    params,
                    parse(location.search)
                )
            );
        } else {
            return this.routerStore.goToNotFound();
        }

This code iterates through each path top-down and tries to find a match. If no path matches, it goes to the not found state. Where is this logic breaking for you?

iexplore commented 5 years ago

Dear Naresh,

Because of your reaction I did further investigation and found the cause why it didn't work for me. In the "not-found" page was a beforeEnter hook that did a throw to an error page to handle the situation. It appears that the hooks are not called for the not-found page. Is this expected behavior?

Anyway, now handling the not-found on the path itself so the problem is solved now.

nareshbhatia commented 5 years ago

I have never tried putting a beforeEnter hook on the not-found path. It is meant to be a simple end destination. Anyway, I am glad that you have figured out a solution.