Top level Components handles client-side navigation state (HTML5 history api) transition
class Link extends React.PureComponent {
static propTypes = {
to: PropTypes.string,
replace: PropTypes.bool,
children: PropTypes.object
}
handleClick = (event) => {
event.preventDefault()
const { replace, to } = this.props
if (!replace)
history.pushState({ to }, 'push', to)
else
history.replaceState({ to }, 'replace', to)
}
render() {
return (
<a href={this.props.to} onClick={this.handleClick}>
{this.props.children}
</a>
)
}
}
class Router extends React.Component{
static propTypes = {
history: PropTypes.object,
children: PropTypes.object
}
constructor(props) {
super(props)
this.state = {
match: {}
}
}
componentWillMount() {
this.unlisten = history.listen(() => {
this.setState({
match: {
path: '',
url: '',
params: {},
isExact: pathname === '/'
}
})
})
}
componentWillUnmount() {
this.unlisten()
}
render() {
const { children } = this.props
return children ? children : null
}
}
class Route extends React.Component {
static propTypes = {
path: PropTypes.string,
component: PropTypes.func, // three different rendering props
render: PropTypes.func,
children: PropTypes.object
}
constructor(props) {
super(props)
this.state = {
match: false
}
}
render() {
const { match } = this.state
const {
component,
render,
children
} = this.props
const props = { history, location, match }
if (component)
return match ? React.createElement(component, props) : null
if (render)
return match ? render(props) : null
if (typeof children === 'function')
return children(props) // children render anyway w/o **match**
return React.Children.only(children)
}
}