useWordCount
Track word and character counts.
useWordCount is a React hook that tracks the word count and character count of the editor's text content. It uses a debounced update listener to avoid recalculating on every keystroke.
Import
import { useWordCount } from "@blokhaus/core";Signature
function useWordCount(debounceMs?: number): {
words: number;
characters: number;
};Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
debounceMs | number | 300 | Debounce delay in milliseconds. Controls how often the count is recalculated after editor changes. |
Return value
| Field | Type | Description |
|---|---|---|
words | number | The number of words in the editor. Returns 0 for empty content. |
characters | number | The total number of characters in the editor (including whitespace). |
Requirements
This hook must be used inside an EditorRoot component. It calls useLexicalComposerContext() internally to access the Lexical editor instance.
Basic usage
Word count display
"use client";
import { useWordCount } from "@blokhaus/core";
function WordCounter() {
const { words, characters } = useWordCount();
return (
<div className="text-sm text-muted-foreground">
{words} words, {characters} characters
</div>
);
}Using with EditorRoot
"use client";
import { EditorRoot, InputRulePlugin, useWordCount } from "@blokhaus/core";
function StatusBar() {
const { words, characters } = useWordCount(500);
return (
<footer className="flex justify-end gap-4 px-4 py-2 border-t text-xs text-gray-500">
<span>{words} words</span>
<span>{characters} chars</span>
</footer>
);
}
export default function EditorPage() {
return (
<EditorRoot
namespace="my-editor"
className="min-h-[400px] p-4 border rounded"
>
<InputRulePlugin />
<StatusBar />
</EditorRoot>
);
}Custom debounce interval
For longer documents where performance matters, increase the debounce interval:
const { words, characters } = useWordCount(1000); // Recalculate at most once per secondImplementation details
The hook works by:
- Registering a Lexical update listener via
editor.registerUpdateListener(). - On each update (debounced), reading the root node's text content via
$getRoot().getTextContent(). - Counting characters as
text.length. - Counting words by trimming the text and splitting on whitespace (
/\s+/). An empty or whitespace-only string returns0words.
The word count uses a simple whitespace-based split
(text.trim().split(/\s+/).length). This works well for Latin-script
languages but may not accurately count words in CJK (Chinese, Japanese,
Korean) text where words are not separated by spaces. For CJK-aware word
counting, you can implement a custom hook using Intl.Segmenter.
Related
- useEditorState -- Hook for reading serialized editor state
- EditorRoot -- The parent component that provides the Lexical context