Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active January 22, 2018 09:19
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanflorence/72891b5cad7d091a5d0f9f11ff467fbe to your computer and use it in GitHub Desktop.
Save ryanflorence/72891b5cad7d091a5d0f9f11ff467fbe to your computer and use it in GitHub Desktop.
import React, { Component } from 'react'
import logo from './logo.svg'
import './App.css'
import { Route, Link, Redirect } from './Zero'
const paths = [ 'one', 'two', 'three' ]
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<h1>Zero Router</h1>
</div>
<ul>
{paths.map(path => (
<li><Link href={'/'+path}>{path}</Link></li>
))}
</ul>
<Route path="/">
{(match) => match.exact ? (
<Redirect to="/one"/>
) : null}
</Route>
{paths.map(path => (
<Route path={'/'+path}>
{(match) => match && (
<h2>{path}</h2>
)}
</Route>
))}
</div>
);
}
}
export default App
import React, { Component } from 'react'
const instances = []
const register = (comp) => instances.push(comp)
const unregister = (comp) => {
instances.splice(instances.indexOf(comp), 1)
}
const push = (path) => {
history.pushState({}, null, path)
instances.forEach(instance => instance.forceUpdate())
}
const replace = (path) => {
history.replaceState({}, null, path)
instances.forEach(instance => instance.forceUpdate())
}
const defaultMatch = (path, url) => {
const match = new RegExp(`^${path}`).exec(url)
return match ? {
url: match[0],
exact: match[0] === path
} : null
}
class Route extends Component {
componentWillMount() {
addEventListener('popstate', this.handlePop)
register(this)
}
handlePop = () => {
this.forceUpdate()
}
componentWillUnmount() {
unregister(this)
removeEventListener('popstate', this.handlePop)
}
render() {
const {
path,
children,
// could pass in a `match` that extracts params
// with path-to-regexp if you wanted to
match = defaultMatch
} = this.props
return children(match(path, location.pathname))
}
}
const isModifiedEvent = (event) =>
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
class Link extends Component {
handleClick = (event) => {
const { onClick, target, replace, href } = this.props
if (onClick)
onClick(event)
if (
!event.defaultPrevented && // onClick prevented default
event.button === 0 && // ignore right clicks
!target && // let browser handle "target=_blank" etc.
!isModifiedEvent(event) // ignore clicks with modifier keys
) {
event.preventDefault()
if (replace) {
replace(href)
} else {
push(href)
}
}
}
render() {
return <a {...this.props} onClick={this.handleClick}/>
}
}
class Redirect extends Component {
componentDidMount() {
(this.props.push ? push : replace)(this.props.to)
}
render() {
return null
}
}
export { Route, Link, Redirect, push, replace }
@ryanflorence
Copy link
Author

I mean ... you really do though, and it's not big anymore, this is just a fun little prototype.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment