preactjs / preact-router

:earth_americas: URL router for Preact.

Home Page:http://npm.im/preact-router

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow URL change but block routing

foxt opened this issue · comments

commented

Hello,

Is it possible to allow the URL to change, but leave the content of the router as is. For example, if I have the following code to show content outside of the router dependent on the path (think Twitter's old design, where tweets would open over top of the content you was looking at, but still changed the URL)

  <div>
    <Match path="/accountSettings">{({ matches }) => matches && <AccountDetailsModal />}</Match>
    <Router>
		<AsyncRoute path='/' .../>
		<AsyncRoute path='/foo' .../>
		<AsyncRoute path='/bar' .../>
	</Router>        
  </div>

Maybe something like onChange that's for example

canRoute={(e) => 
    if (e.url == '/accountSettings') return false;
    else return true;
}}

or:

<Router>
		<AsyncRoute path='/' .../>
		<AsyncRoute path='/foo' .../>
		<AsyncRoute path='/bar' .../>
		<FakeRoute path='/accountSettings' />
</Router>
commented

You might be able to hack this in with

	/** Re-render children with a new URL to match against. */
	routeTo(url) {
        let matchingRoute = this._getMatchingChild(toChildArray(this.props.children), url)
        if (matchingRoute === undefined) return false;
        if (matchingRoute[0].props && matchingRoute[0].props.prevent) return true;

		this.setState({ url });

		// trigger a manual re-route if we're not in the middle of an update:
		if (!this._updating) this.forceUpdate();

		return true;
	},

ymmv

What you want to do is route the new URL to the same component is all, and handle the changed router state from there. You can't skip the router without making the new URL unusable. For example,

import { Router } from 'preact-router';

function ExampleRoute({ optionalId }) {
  return (
    <div>
      {optionalId && <h1>Pretend I'm an overlay</h1>}
      <h1>Show overlay via link</h1>
      <a href="/12345">Click here</a>
    </div>
  );
}

export function App() {
  return (
    <div>
      <Router>
        <ExampleRoute path="/:optionalId?" />
      </Router>
    </div>
  );
}

Edit: Here's a (much prettier) StackBlitz example