Lusito / react-nano

Tiny, powerful and type-safe React libraries. All released under a liberal license
https://lusito.github.io/react-nano/
zlib License
34 stars 3 forks source link

`router`: A way to prevent `replaceState` and `pushState` #3

Closed silverwind closed 5 months ago

silverwind commented 9 months ago

To implement navigation warnings like "Are you sure to leave this unsaved page?" it would be nice if there were a way to prevent replaceState and pushState, ideally in a async fashing.

How about adding a shouldAbortNavigation option to the Router that accepts a function that, if present, is awaited and if it returns true, abort the navigation?

Lusito commented 5 months ago

Hi @silverwind, sorry for the delay. Life kept me very busy.

Sounds like a valid request. Would this API work?

<Router onNavigate={onNavigate} ...>

with:

export type OnNavigateData = {
    from: string;
    to: string;
    type: "push" | "replace";
};
export type OnNavigateFn = (data: OnNavigateData) => Promise<boolean>;

export interface RouterHistory {
    push: (path: string) => Promise<boolean>;
    replace: (path: string) => Promise<boolean>;
}

export interface RouterProps {
    ....
    /**
     * An async callback that will be called on a navigation event.
     * If it resolves to false, the navigation event will be aborted
     */
    onNavigate?: OnNavigateFn;
}
silverwind commented 5 months ago

Sounds good. I would change the return type to accept both sync and async:

export type OnNavigateFn = (data: OnNavigateData) => Promise<boolean> | boolean;

Implementation should be the same, you just await onNavigateFn.

Lusito commented 5 months ago

A new version has been released.