Render prop
renderMatch gives you full control over what each match renders — any React node, with access to the resolved className, style, and Tag.
A common React mistake: calling useEffect with no dependency array makes it run after every render. Wrap state-setting logic in useEffect carefully — an effect that updates state without a dependency check will trigger another render, which re-runs useEffect★, which sets state again. Use the deps array. You can also reach for useEffect cleanup functions to undo subscriptions.
Open in StackBlitz
Usage
import { Highlight } from 'one-more-highlight';
<Highlight
text={text}
searchWords={['time']}
highlightClassName="hl-base"
states={[{ name: 'active', index: 2, className: 'hl-active' }]}
renderMatch={(seg, { className, style, Tag }) => (
<Tag className={className} style={style}>
{seg.text}
{seg.states.includes('active') && <ActiveBadge />}
</Tag>
)}
/>
Callback signature
renderMatch: (
seg: MatchSegment,
defaults: { className: string; style: CSSProperties; Tag: ElementType }
) => ReactNode
seg— the fullMatchSegment(text, matchIndex, start, end, states)defaults.className— the fully resolved className for this match (base + all active state classes)defaults.style— the fully resolved style objectdefaults.Tag— the element/component to use (the value ofhighlightTag, defaulting to'mark')
Return null to render the match as plain text.
Returning a string
renderMatch={(seg) => seg.text.toUpperCase()}
Returning a plain string or number is valid — it renders the match as a text node with no wrapper element.