Support relative links
Would love to see support for relative links in Wouter!
URL: https://www.example.com/some/long/unnested/route/foo
<Link to="../bar">Takes you to example.com/some/long/unnested/route/bar</Link>
I appreciate we can nest things but that's not always an appropriate option.
It's not something we have in the roadmap, but maybe this can be solved with a custom wrapper around Link component e.g.
// under the hood, takes current location from `useLocation`, resolves the absolute path and renders a regular Link
<RelLink to="../bar" />
If you get it working, please let me know, maybe we can add this to the README.
I am not sure I understood the assignment correctly, but I have a similar issue. For me thinking in terms of "unix" paths is easier when building my routes.
For now, I've settled with this solution:
import { useCallback } from 'react';
import { useLocation, useRouter } from 'wouter';
type Return = ReturnType<typeof useLocation>;
function join(...paths: string[]): string {
const parts = paths.flatMap(p => p.split('/'));
const newParts: string[] = [];
for (const part of parts) {
if (part === '' || part === '.') {
continue;
}
if (part === '..') {
newParts.pop();
} else {
newParts.push(part);
}
}
if (newParts.length === 0) {
return '/';
}
return '/' + newParts.join('/');
}
export function useRelativeLocation(base = '/'): Return {
const { hook } = useRouter();
const [location, navigate] = hook(); // `useBrowserLocation` by default
const relativeNavigate = useCallback(
(to: string, options: Parameters<Return[1]>[1]) => {
if (to.startsWith('.')) {
const newPath = join(location, to);
if (base === '/' || newPath === base || newPath.startsWith(`${base}/`)) {
return navigate(newPath, options);
}
} else if (to.startsWith('/')) {
if (base === '/' || to === base || to.startsWith(`${base}/`)) {
return navigate(to, options);
}
}
return navigate(base);
},
[base, location, navigate],
);
return [location, relativeNavigate];
}
Note that the base param is passed to useRelativeLocation because the base returned in useRouter is messed up by nesting contexts. Also when trying to navigate outside the basePath, instead of adding it automatically, it defaults on going back to the base path, which may or may not be what you wanted.
Implementing matching <Link> and <Redirect> should be easy, so I didn't include them here.