preact-router icon indicating copy to clipboard operation
preact-router copied to clipboard

Option to disable default link behavior

Open tysonmatanich opened this issue 6 years ago • 4 comments

It would be nice to have a configuration option to disable the default link behavior for an entire project or under a specific path. In this scenario, instead of automatically trying to perform routing, it would rely on a Link component or perhaps a routed attribute.

<Link href="/foo">Foo</Link>
<a href="/foo" routed>Foo</a>

Currently, you can manually opt out using the native attribute, but then you must add it to every link.

<a href="/foo" native>Foo</a>

tysonmatanich avatar Nov 30 '18 21:11 tysonmatanich

Seems like this approach would be helpful for #260.

tysonmatanich avatar Nov 30 '18 21:11 tysonmatanich

One suggestion: links that don't match any routes automatically fall back to the default browser behaviour. If you want to avoid preact-router routing for a given path, you could avoid using default routes.

developit avatar Feb 01 '19 19:02 developit

A default route is required for showing a 404 not found page.

tysonmatanich avatar Feb 01 '19 19:02 tysonmatanich

For sure. I've found that in the cases where I need to exempt whole paths on the same domain, I'm not usually rendering the 404's with Preact since those paths also need 404's.

Trying to think of an elegant solution here, but it's tough. We do have a Link component that does what you describe, so perhaps something like an attribute on Router that disables auto-linking? Unfortunately right now the handler for this is a singleton since it applies to the whole document (links outside of <Router> need to be handled).

Here's an option that would let you blacklist preact's routing for links matching a regex:

import { options } from 'preact';

const blacklist = /^\/some-section/;

const old = options.vnode;
options.vnode = vnode => {
  if (vnode.nodeName === 'a') {
    const href = vnode.attributes.href;
    if (href && blacklist.test(href)) {
      vnode.attributes.native = true;
    }
  }
  old(vnode);
};

Another approach would be to use a custom Link component:

const Link = ({ routed, ...props }) => <a native={!routed} {...props} />
// <Link routed href="/foo">Foo</Link>  // uses client side routing
// <Link href="/foo">Foo</Link>  // defaults to browser navigation

(hope these are at least a bit helpful!)

developit avatar Feb 01 '19 19:02 developit