wouter icon indicating copy to clipboard operation
wouter copied to clipboard

Make a more robust nested routing structure possible

Open HansBrende opened this issue 3 years ago • 3 comments

Here's my basic idea. Fixes #225 while remaining fully backwards compatible. Alternative to #226. For the nested router use-case, it will now be possible to do:

function NestedRouter(props) {
    return <Router {...props} parent={useRouter()}/>
}

If this PR gets some traction, I can update type definitions as needed.

HansBrende avatar Jan 30 '22 22:01 HansBrende

FYI, this PR will also allow some really cool stuff like a stable useNavigate function relative to your current router context. E.g.:

const useNavigateFromRouterContext = (ctx: RouterProps) => React.useCallback(
    (to: Path, options?: {replace?: boolean}) => {
        window.history[options?.replace ? "replaceState" : "pushState"](null, "",
            to[0] === "~" ? to.slice(1) : 
            ctx.base + (to && !to.startsWith('/') && !ctx.base.endsWith('/') ? `/${to}` : to))
    }, [ctx]); // Do NOT depend on ctx.base! Unreliable, and also will cause this callback to un-memoize.

export const useNavigate = () => useNavigateFromRouterContext(useRouter());

HansBrende avatar Jan 30 '22 22:01 HansBrende

@molefrog any thoughts on this PR? I can update the type definitions and stuff if you like my changes.

HansBrende avatar Feb 02 '22 00:02 HansBrende

I was about to begrudgingly switch to react-router but this PR makes me think I should wait! I'll be keeping an eye on this PR because it's something that I really need in my current project. Props to @HansBrende for the great idea

Scott-Fischer avatar Feb 06 '22 20:02 Scott-Fischer

Hey @HansBrende. It took me a while to wrap my head around your solution, it was really smart and nice approach, however there was something in the API design that was bothering me.

I realised that we could get the closest parent router from the context, and also assume that routers are immutable — they actually never change within a particular component node, even if <Router /> starts receiving different props, in reality it's really hard to handle these updates, mostly because it could lead to some weird behaviour (imagine that you try to change the hook, it'll break the app).

Would you mind taking a look at #265? It also gave some nice size reduction.

molefrog avatar Nov 15 '22 09:11 molefrog

Closing in favour of #265

molefrog avatar Nov 15 '22 21:11 molefrog