Skip to content

Commit

Permalink
Refactor Highlight to be a functional component, fix not re-rendering…
Browse files Browse the repository at this point in the history
… on content change
  • Loading branch information
ewanharris committed Mar 29, 2023
1 parent cb6e53e commit d993928
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 75 deletions.
92 changes: 21 additions & 71 deletions Sample-01/src/components/Highlight.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,23 @@
import React, { Component } from "react";
import PropTypes from "prop-types";

import hljs from "highlight.js";
import "highlight.js/styles/monokai-sublime.css";

const registeredLanguages = {};

class Highlight extends Component {
constructor(props) {
super(props);

this.state = { loaded: false };
this.codeNode = React.createRef();
}

componentDidMount() {
const { language } = this.props;

if (language && !registeredLanguages[language]) {
try {
const newLanguage = require(`highlight.js/lib/languages/${language}`);
hljs.registerLanguage(language, newLanguage);
registeredLanguages[language] = true;

this.setState({ loaded: true }, this.highlight);
} catch (e) {
console.error(e);
throw Error(`Cannot register the language ${language}`);
}
} else {
this.setState({ loaded: true });
}
}

componentDidUpdate() {
this.highlight();
}

highlight = () => {
this.codeNode &&
this.codeNode.current &&
hljs.highlightBlock(this.codeNode.current);
};

render() {
const { language, children } = this.props;
const { loaded } = this.state;

if (!loaded) {
return null;
}

return (
<pre className="rounded">
<code ref={this.codeNode} className={language}>
{children}
</code>
</pre>
);
}
}

Highlight.propTypes = {
children: PropTypes.node.isRequired,
language: PropTypes.string,
};

Highlight.defaultProps = {
language: "json",
import React, { useEffect, useRef } from 'react';

import hljs from 'highlight.js';
import 'highlight.js/styles/monokai-sublime.css';

const Highlight = (props) => {
const { text, language = 'json' } = props;

const codeNode = useRef(null);
useEffect(() => {
hljs.highlightElement(codeNode.current);
}, [text]);

return (
<pre className="rounded">
<code ref={codeNode} className={language}>
{text}
</code>
</pre>
);
};

export default Highlight;
export default Highlight;
4 changes: 1 addition & 3 deletions Sample-01/src/views/ExternalApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,7 @@ export const ExternalApiComponent = () => {
{state.showResult && (
<div className="result-block" data-testid="api-result">
<h6 className="muted">Result</h6>
<Highlight>
<span>{JSON.stringify(state.apiMessage, null, 2)}</span>
</Highlight>
<Highlight text={JSON.stringify(state.apiMessage, null, 2)} />
</div>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion Sample-01/src/views/Profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const ProfileComponent = () => {
</Col>
</Row>
<Row>
<Highlight>{JSON.stringify(user, null, 2)}</Highlight>
<Highlight text={JSON.stringify(user, null, 2)} />
</Row>
</Container>
);
Expand Down

0 comments on commit d993928

Please sign in to comment.