Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active April 9, 2018 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanflorence/63b458fa6a92857c18e89e23672bc259 to your computer and use it in GitHub Desktop.
Save ryanflorence/63b458fa6a92857c18e89e23672bc259 to your computer and use it in GitHub Desktop.
import Route from 'react-router/Route'
import React from 'react'
class FocusManager extends React.Component {
componentDidMount() {
this.focus()
}
componentDidUpate(prevProps) {
if (this.props.location !== prevProps.location) {
this.focus()
}
}
focus() {
// prevent parent route from stealing focus from child route since
// didMount/didUpdate calls the parents after children
if (!this.ref.contains(document.activeElement)) {
// only steal focus from non-routes (maybe focus is on a link inside)
// the route
if (document.activeElement.getAttribute('data-route') == null) {
this.ref.focus()
}
}
}
render() {
// could use React.forwardRef to avoid this div
return (
<div tabIndex="-1" data-route="true" ref={n => this.ref = n}>{this.props.children}</div>
)
}
}
export default ({path, component:Component}) => (
<Route path={path} render={(props) => (
<FocusManager {...props}>
<Component {...props}/>
</FocusManager>
)}/>
)
// usage
import FocusableRoute from '../FocusableRoute'
<FocusableRoute path="/whatever" component={Whatever}/>
// if nested, the last one wins
<FocusableRoute path="/whatever" component={Whatever}/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment