Skip to content

Commit

Permalink
Merge branch 'master' into fix-ssr-memleak
Browse files Browse the repository at this point in the history
  • Loading branch information
sadnessOjisan committed Jun 24, 2021
2 parents 1d8226a + 5fb140e commit d3e849a
Show file tree
Hide file tree
Showing 32 changed files with 13,490 additions and 936 deletions.
9 changes: 0 additions & 9 deletions .babelrc

This file was deleted.

66 changes: 0 additions & 66 deletions .eslintrc

This file was deleted.

4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/dist
/coverage
/node_modules
/npm-debug.log
/match.js
/*.d.ts
.DS_Store
/match/*.js
143 changes: 133 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# preact-router

[![NPM](http://img.shields.io/npm/v/preact-router.svg)](https://www.npmjs.com/package/preact-router)
[![NPM](https://img.shields.io/npm/v/preact-router.svg)](https://www.npmjs.com/package/preact-router)
[![travis-ci](https://travis-ci.org/developit/preact-router.svg)](https://travis-ci.org/developit/preact-router)

Connect your [Preact] components up to that address bar.
Expand All @@ -9,9 +9,10 @@ Connect your [Preact] components up to that address bar.

> 💁 **Note:** This is not a preact-compatible version of React Router. `preact-router` is a simple URL wiring and does no orchestration for you.
>
> If you're looking for more complex solutions like nested routes and view composition, [react-router](https://github.com/ReactTraining/react-router) works great with preact as long as you alias in [preact-compat](https://github.com/developit/preact-compat). React Router 4 even [works directly with Preact](http://codepen.io/developit/pen/BWxepY?editors=0010), no compatibility layer needed!
> If you're looking for more complex solutions like nested routes and view composition, [react-router](https://github.com/ReactTraining/react-router) works great with preact as long as you alias in [preact/compat](https://preactjs.com/guide/v10/getting-started#aliasing-react-to-preact).
#### [See a Real-world Example :arrow_right:](https://jsfiddle.net/developit/qc73v9va/)

#### [See a Real-world Example :arrow_right:](http://jsfiddle.net/developit/qc73v9va/)

---

Expand All @@ -37,25 +38,29 @@ render(<Main />, document.body);

If there is an error rendering the destination route, a 404 will be displayed.


### Handling URLS

:information_desk_person: Pages are just regular components that get mounted when you navigate to a certain URL.
Any URL parameters get passed to the component as `props`.

Defining what component(s) to load for a given URL is easy and declarative.
You can even mix-and-match URL parameters and normal `props`.
You can also make params optional by adding a `?` to it.
Querystring and `:parameter` values are passed to the matched component as props.
Parameters can be made optional by adding a `?`, or turned into a wildcard match by adding `*` (zero or more characters) or `+` (one or more characters):

```js
<Router>
<A path="/" />
<B path="/b" id="42" />
<C path="/c/:id" />
<C path="/d/:optional?/:params?" />
<D default />
<D path="/e/:remaining_path*" />
<E path="/f/:remaining_path+" />
<F default />
</Router>
```


### Lazy Loading

Lazy loading (code splitting) with `preact-router` can be implemented easily using the [AsyncRoute](https://www.npmjs.com/package/preact-async-route) module:
Expand All @@ -76,6 +81,7 @@ import AsyncRoute from 'preact-async-route';
</Router>
```


### Active Matching & Links

`preact-router` includes an add-on module called `match` that lets you wire your components up to Router changes.
Expand Down Expand Up @@ -135,17 +141,62 @@ render(
)
```


### Default Link Behavior

Sometimes it's necessary to bypass preact-router's link handling and let the browser perform routing on its own.

This can be accomplished by adding a `native` boolean attribute to any link:

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

### Detecting Route Changes

The `Router` notifies you when a change event occurs for a route with the `onChange` callback:

```js
import { render, Component } from 'preact';
import { Router, route } from 'preact-router';

class App extends Component {

// some method that returns a promise
isAuthenticated() { }

handleRoute = async e => {
switch (e.url) {
case '/profile':
const isAuthed = await this.isAuthenticated();
if (!isAuthed) route('/', true);
break;
}
};

render() {
return (
<Router onChange={this.handleRoute}>
<Home path="/" />
<Profile path="/profile" />
</Router>
);
}

}
```

### Redirects

Can easily be impleted with a custom `Redirect` component;
Can easily be implemented with a custom `Redirect` component;

```js
import { Component } from 'preact';
import { route } from 'preact-router';

export default class Redirect extends Component {
componentWillMount() {
route(this.props.to);
route(this.props.to, true);
}

render() {
Expand All @@ -163,13 +214,85 @@ Now to create a redirect within your application, you can add this `Redirect` co
</Router>
```

---

### Custom History

It's possible to use alternative history bindings, like `/#!/hash-history`:

```js
import { h } from 'preact';
import Router from 'preact-router';
import { createHashHistory } from 'history';

const Main = () => (
<Router history={createHashHistory()}>
<Home path="/" />
<About path="/about" />
<Search path="/search/:query" />
</Router>
);

render(<Main />, document.body);
```

### Programmatically Triggering Route

It's possible to programmatically trigger a route to a page (like `window.location = '/page-2'`)

```js
import { route } from 'preact-router';

route('/page-2') // appends a history entry

route('/page-3', true) // replaces the current history entry
```

### Nested Routers

The `<Router>` is a self-contained component that renders based on the page URL. When nested a Router inside of another Router, the inner Router does not share or observe the outer's URL or matches. Instead, inner routes must include the full path to be matched against the page's URL:

```js
import { h, render } from 'preact';
import Router from 'preact-router';

function Profile(props) {
// `props.rest` is the rest of the URL after "/profile/"
return (
<div>
<h1>Profile</h1>
<Router>
<MyProfile path="/profile/me" />
<UserProfile path="/profile/:user" />
</Router>
</div>
);
}
const MyProfile = () => (<h2>My Profile</h2>);
const UserProfile = (props) => (<h2>{props.user}</h2>);

function App() {
return (
<div>
<Router>
<Home path="/" />
<Profile path="/profile/:rest*" />
</Router>
<nav>
<a href="/">Home</a>
<a href="/profile/me">My Profile</a>
<a href="/profile/alice">Alice's Profile</a>
</nav>
</div>
);
}
render(<App />, document.body);
```
### License
[MIT]
[Preact]: https://github.com/developit/preact
[MIT]: http://choosealicense.com/licenses/mit/
[MIT]: https://choosealicense.com/licenses/mit/
10 changes: 8 additions & 2 deletions src/index.d.ts → index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export class Router extends preact.Component<RouterProps, {}> {
render(props: RouterProps, {}): preact.VNode;
}

export const subscribers: Array<(url: string) => void>

type AnyComponent<Props> =
| preact.FunctionalComponent<Props>
| preact.ComponentConstructor<Props, any>;
Expand All @@ -60,6 +62,10 @@ export function Route<Props>(
props: RouteProps<Props> & Partial<Props>
): preact.VNode;

export function Link(props: {activeClassName?: string} & JSX.HTMLAttributes): preact.VNode;
export function Link(props: {activeClassName?: string} & preact.JSX.HTMLAttributes): preact.VNode;

declare module 'preact' {
export interface Attributes extends RoutableProps {}
}

export default Router;
export default Router;
33 changes: 0 additions & 33 deletions karma.conf.js

This file was deleted.

16 changes: 16 additions & 0 deletions match/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as preact from 'preact';

import { Link as StaticLink, RoutableProps } from '..';

export class Match extends preact.Component<RoutableProps, {}> {
render(): preact.VNode;
}

export interface LinkProps extends preact.JSX.HTMLAttributes {
activeClassName?: string;
children?: preact.ComponentChildren;
}

export function Link(props: LinkProps): preact.VNode;

export default Match;
13 changes: 13 additions & 0 deletions match/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "index",
"module": "./index.es.js",
"main": "./index.js",
"types": "./index.d.ts",
"scripts": {
"build": "microbundle src/index.js -f es -o . --no-sourcemap && microbundle src/cjs.js -f cjs -o . --no-sourcemap"
},
"peerDependencies": {
"preact": "*",
"preact-router": "*"
}
}
4 changes: 4 additions & 0 deletions match/src/cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Match, Link } from './index';

Match.Link = Link;
export default Match;
Loading

0 comments on commit d3e849a

Please sign in to comment.