Skip to content

Instantly share code, notes, and snippets.

@Steven24K
Created May 3, 2021 10:07
Show Gist options
  • Save Steven24K/4ff91c61042af3a3f0ce4400fbaa13d8 to your computer and use it in GitHub Desktop.
Save Steven24K/4ff91c61042af3a3f0ce4400fbaa13d8 to your computer and use it in GitHub Desktop.
A little wrapper that can be used to keep track of the innerHtml inside react components.
import * as React from "react"
interface InnerHtmlWrapperProps {
text: string
className?: string
}
/**
* A component that puts the text inside a div using dangerouslySetInnerHTML to keep the html layout. Inside this component an internal ref is used to keep track of the content inside the div.
* When you are working with react you have full control over the DOM and the placement new HTML tags, manipulate attributes and event listeners. However when you deal with HTML encoded content you lose
* that control. The only thing that is kept is the html layout. For instance when you want to do a check on external links and open those in a new tab, setting the target to _blank you can't do that.
* You could write additional Javascript to that check, insert a script using react helmet inside the particular component, but those approaches can affect the entire website. You want the logic to only happen
* inside your component.
*
* To regain control over the innerHtml you can use a component ref. This is only visible to the component and allows you to perform operations on it using basic Javascript. You can get then for instance all the
* links inside the innerHtml check if they are external and set the target to blank. The scripts are being executed inside the componentDidMount and do not affect the entire site. The scripts are being ran isolated
* inside the component.
*/
export class InnerHtmlWrapper extends React.Component<InnerHtmlWrapperProps, {}> {
private textFieldRef: React.RefObject<HTMLDivElement>
constructor(props: InnerHtmlWrapperProps) {
super(props)
this.state = {}
this.textFieldRef = React.createRef()
}
componentDidMount() {
let links = this.textFieldRef.current.getElementsByTagName('a')
// Make all links open in a new tab
for (let i = 0; i < links.length; i++) {
links.item(i).target = "_blank"
}
// Manipulate your plain HTML here ...
}
render() {
return <div className={this.props.className} ref={this.textFieldRef} dangerouslySetInnerHTML={{ __html: this.props.text }} />
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment