Last active
May 28, 2017 21:04
-
-
Save brandondurham/39e81ac1d0368b6a3ce2660c3dc230f6 to your computer and use it in GitHub Desktop.
Higher-order component to ensure all static, same-domain links loaded from external sources use the router method
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// To use with your component as a decorator: | |
import React from 'react'; | |
import styles from './styles.css'; | |
import Internalize from 'components/InternalLinks'; | |
@Internalize | |
export default class BlogContent extends React.Component { | |
static propTypes = { | |
content: PropTypes.static.isRequired | |
}; | |
render() { | |
const { content } = this.props; | |
return ( | |
<article className={ styles.containerClassName }> | |
{ content } | |
</article> | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// As a higher-order component: | |
import React from 'react'; | |
import styles from './styles.css'; | |
import Internalize from 'components/InternalLinks'; | |
export class BlogContent extends React.Component { | |
static propTypes = { | |
content: PropTypes.static.isRequired | |
}; | |
render() { | |
const { content } = this.props; | |
return ( | |
<article className={ styles.containerClassName }> | |
{ content } | |
</article> | |
); | |
} | |
} | |
export default Internalize(BlogContent); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// InternalLinks.js | |
/** | |
* Internal Links | |
* | |
* Handle all clicks that occur within a component or container that loads | |
* external content. If the click is on an link to another page within the app | |
* (domain matching, absolute and relative links), ensure it’s handled with the Router. | |
*/ | |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import localLinks from 'local-links'; | |
export default function (WrappedComponent) { | |
return class InternalLinks extends React.Component { | |
static propTypes = { | |
changeRoute: React.PropTypes.func | |
} | |
componentDidMount() { | |
ReactDOM.findDOMNode(this).addEventListener('click', this.handleAnchorClick, false); | |
} | |
componentWillUnmount() { | |
ReactDOM.findDOMNode(this).removeEventListener('click', this.handleAnchorClick, false); | |
} | |
handleAnchorClick = (event) => { | |
const { changeRoute } = this.props; | |
if (ReactDOM.findDOMNode(this) && ReactDOM.findDOMNode(this).contains(event.target)) { | |
const isAnchor = event.target.nodeName.toLowerCase() === 'a'; | |
const isLocal = localLinks.getLocalPathname(event); | |
// If the clicked element is an anchor and points to a page | |
// within the app, replace the default event with a route change. | |
if (isAnchor && isLocal) { | |
event.preventDefault(); | |
changeRoute(event.target.pathname); | |
} | |
} | |
}; | |
render() { return <WrappedComponent {...this.props} />; } | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment