Skip to content

Commit 626c5b6

Browse files
authored
fix: reload highlighter when language is available (#2601)
* fix: reload highlighter when language is available - add language to list of deps, to trigger a re-render once available - persist highlighter loader in a ref, to avoid unnecessary rerenders - memoize language computation from className * prevent loading the highlighter when component unmounts; remove import caching; stabilize CodeSkeleton - import caching is not needed as dynamic from nextjs already does that - CodeSkeleton depends on changing props, they're now part of the callback dependencies * remove unnecessary deps from loadHighlighter callback
1 parent 1342317 commit 626c5b6

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

components/text.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,11 @@ function CodeSkeleton ({ className, children, ...props }) {
263263
function Code ({ node, inline, className, children, style, ...props }) {
264264
const [ReactSyntaxHighlighter, setReactSyntaxHighlighter] = useState(null)
265265
const [syntaxTheme, setSyntaxTheme] = useState(null)
266-
const language = className?.match(/language-(\w+)/)?.[1] || 'text'
266+
// avoid re-computing language when className doesn't change
267+
const language = useMemo(
268+
() => className?.match(/language-(\w+)/)?.[1] || 'text',
269+
[className]
270+
)
267271

268272
const loadHighlighter = useCallback(() =>
269273
Promise.all([
@@ -272,18 +276,25 @@ function Code ({ node, inline, className, children, style, ...props }) {
272276
loading: () => <CodeSkeleton className={className} {...props}>{children}</CodeSkeleton>
273277
}),
274278
import('react-syntax-highlighter/dist/cjs/styles/hljs/atom-one-dark').then(mod => mod.default)
275-
]), []
279+
// className is necessary to re-compute language
280+
]), [className]
276281
)
277282

278283
useEffect(() => {
279-
if (!inline && language !== 'math') { // MathJax should handle math
280-
// loading the syntax highlighter and theme only when needed
281-
loadHighlighter().then(([highlighter, theme]) => {
282-
setReactSyntaxHighlighter(() => highlighter)
284+
if (inline || language === 'math') return // MathJax should handle math
285+
286+
let aborted = false
287+
loadHighlighter().then(([Highlighter, theme]) => {
288+
if (!aborted) {
289+
setReactSyntaxHighlighter(() => Highlighter)
283290
setSyntaxTheme(() => theme)
284-
})
291+
}
292+
})
293+
294+
return () => {
295+
aborted = true
285296
}
286-
}, [inline])
297+
}, [inline, language, loadHighlighter])
287298

288299
if (inline || !ReactSyntaxHighlighter) { // inline code doesn't have a border radius
289300
return (

0 commit comments

Comments
 (0)