Skip to content

Commit abb0223

Browse files
committed
Refactor Highlight to be a functional component, fix not re-rendering on content change
1 parent f1ee00b commit abb0223

File tree

3 files changed

+23
-75
lines changed

3 files changed

+23
-75
lines changed

Sample-01/src/components/Highlight.js

Lines changed: 21 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,23 @@
1-
import React, { Component } from "react";
2-
import PropTypes from "prop-types";
3-
4-
import hljs from "highlight.js";
5-
import "highlight.js/styles/monokai-sublime.css";
6-
7-
const registeredLanguages = {};
8-
9-
class Highlight extends Component {
10-
constructor(props) {
11-
super(props);
12-
13-
this.state = { loaded: false };
14-
this.codeNode = React.createRef();
15-
}
16-
17-
componentDidMount() {
18-
const { language } = this.props;
19-
20-
if (language && !registeredLanguages[language]) {
21-
try {
22-
const newLanguage = require(`highlight.js/lib/languages/${language}`);
23-
hljs.registerLanguage(language, newLanguage);
24-
registeredLanguages[language] = true;
25-
26-
this.setState({ loaded: true }, this.highlight);
27-
} catch (e) {
28-
console.error(e);
29-
throw Error(`Cannot register the language ${language}`);
30-
}
31-
} else {
32-
this.setState({ loaded: true });
33-
}
34-
}
35-
36-
componentDidUpdate() {
37-
this.highlight();
38-
}
39-
40-
highlight = () => {
41-
this.codeNode &&
42-
this.codeNode.current &&
43-
hljs.highlightBlock(this.codeNode.current);
44-
};
45-
46-
render() {
47-
const { language, children } = this.props;
48-
const { loaded } = this.state;
49-
50-
if (!loaded) {
51-
return null;
52-
}
53-
54-
return (
55-
<pre className="rounded">
56-
<code ref={this.codeNode} className={language}>
57-
{children}
58-
</code>
59-
</pre>
60-
);
61-
}
62-
}
63-
64-
Highlight.propTypes = {
65-
children: PropTypes.node.isRequired,
66-
language: PropTypes.string,
67-
};
68-
69-
Highlight.defaultProps = {
70-
language: "json",
1+
import React, { useEffect, useRef } from 'react';
2+
3+
import hljs from 'highlight.js';
4+
import 'highlight.js/styles/monokai-sublime.css';
5+
6+
const Highlight = (props) => {
7+
const { text, language = 'json' } = props;
8+
9+
const codeNode = useRef(null);
10+
useEffect(() => {
11+
hljs.highlightElement(codeNode.current);
12+
}, [text]);
13+
14+
return (
15+
<pre className="rounded">
16+
<code ref={codeNode} className={language}>
17+
{text}
18+
</code>
19+
</pre>
20+
);
7121
};
7222

73-
export default Highlight;
23+
export default Highlight;

Sample-01/src/views/ExternalApi.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,7 @@ export const ExternalApiComponent = () => {
185185
{state.showResult && (
186186
<div className="result-block" data-testid="api-result">
187187
<h6 className="muted">Result</h6>
188-
<Highlight>
189-
<span>{JSON.stringify(state.apiMessage, null, 2)}</span>
190-
</Highlight>
188+
<Highlight text={JSON.stringify(state.apiMessage, null, 2)} />
191189
</div>
192190
)}
193191
</div>

Sample-01/src/views/Profile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const ProfileComponent = () => {
2424
</Col>
2525
</Row>
2626
<Row>
27-
<Highlight>{JSON.stringify(user, null, 2)}</Highlight>
27+
<Highlight text={JSON.stringify(user, null, 2)} />
2828
</Row>
2929
</Container>
3030
);

0 commit comments

Comments
 (0)