Skip to main content

React

Examples:

@lumis-sh/react follows the same formatter-first API as the rest of Lumis, but splits client and server helpers.

Install

npm install @lumis-sh/react @lumis-sh/lumis @lumis-sh/themes react

Client component

Use CodeBlock when you want a drop-in React component.

Simple

import {CodeBlock} from '@lumis-sh/react'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import latte from '@lumis-sh/themes/catppuccin_latte'
const codeString = `export function Hello() {
return <h1>Hello</h1>
}`
export function Example() {
return (
<CodeBlock formatter={htmlInline({language: 'tsx', theme: latte})}>
{codeString}
</CodeBlock>
)
}

Reuse one highlighter

import {CodeBlock} from '@lumis-sh/react'
import {createHighlighter} from '@lumis-sh/lumis'
import {bundledLanguages} from '@lumis-sh/lumis/bundles/web'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import latte from '@lumis-sh/themes/catppuccin_latte'
const highlighter = createHighlighter({languages: [bundledLanguages]})
const codeString = `export function Hello() {
return <h1>Hello</h1>
}`
export function Example() {
return (
<CodeBlock
highlighter={highlighter}
formatter={htmlInline({language: bundledLanguages.tsx, theme: latte})}
>
{codeString}
</CodeBlock>
)
}

If you do not pass highlighter, CodeBlock uses a shared internal highlighter. Passing your own highlighter is the better choice when you want to register bundles or reuse one instance across many blocks.

Hook

Use useLumis() when you want to control the loading UI yourself.

import {useLumis} from '@lumis-sh/react'
import {createHighlighter} from '@lumis-sh/lumis'
import {bundledLanguages} from '@lumis-sh/lumis/bundles/web'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import latte from '@lumis-sh/themes/catppuccin_latte'
const highlighter = createHighlighter({languages: [bundledLanguages]})
export function Example() {
const {content, error, isLoading} = useLumis({
children: 'export const answer = 42',
formatter: htmlInline({language: 'typescript', theme: latte}),
highlighter,
})
if (isLoading) return <p>Loading syntax highlighter...</p>
if (error) return <p>{error.message}</p>
return <>{content}</>
}

error is an Error when highlighting or language loading fails, and undefined otherwise.

Server rendering

Use renderCodeBlock() from the server subpath when you need highlighted output on the server.

This is a good fit for React Server Components and Next.js App Router pages.

import {renderCodeBlock} from '@lumis-sh/react/server'
import {bundledLanguages} from '@lumis-sh/lumis/bundles/web'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import latte from '@lumis-sh/themes/catppuccin_latte'
const codeString = `export function Hello() {
return <h1>Hello</h1>
}`
export async function Article() {
const block = await renderCodeBlock({
children: codeString,
formatter: htmlInline({language: bundledLanguages.tsx, theme: latte}),
})
return <article>{block}</article>
}

Reusing one highlighter

Create one Highlighter and pass it into CodeBlock or useLumis():

import {createHighlighter} from '@lumis-sh/lumis'
import {bundledLanguages} from '@lumis-sh/lumis/bundles/web'
import {CodeBlock} from '@lumis-sh/react'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import latte from '@lumis-sh/themes/catppuccin_latte'
const codeString = `export const answer = 42`
const highlighter = await createHighlighter({languages: [bundledLanguages]})
export function Example() {
return (
<CodeBlock
highlighter={highlighter}
formatter={htmlInline({language: 'tsx', theme: latte})}
>
{codeString}
</CodeBlock>
)
}

This is the best option when you want to register a bundle and render many code blocks on one page.

Behavior

  • formatter is the single source of truth for the language
  • CodeBlock and useLumis() are client exports from @lumis-sh/react
  • renderCodeBlock() is a server export from @lumis-sh/react/server
  • the React helpers call highlighter.loadLanguage(formatter.language) before highlighting
  • when the language is already loaded, Lumis reuses the cached result
  • for true server-rendered highlighting, prefer renderCodeBlock()
  • CodeBlock and useLumis() re-highlight when children, formatter, or highlighter changes