Hooks
Use React hooks to read editor state, run commands, search documents, and configure pages.
Call these hooks inside <DocxEditor.Root>.
You can also call them inside <DocxEditor>, which renders that root.
The hooks read the editor from React context.
The packaged toolbar, menu, and navigation pane use the same hooks.
useEditorCommand
Pass a chrome slot ID to useEditorCommand. The
chrome slot reference lists every available
ID and its named toolbar part.
The hook returns the state and action for a control:
import { useEditorCommand } from '@docx-editor.dev/react';
function BoldButton() {
const bold = useEditorCommand('text.bold');
return (
<button
onMouseDown={(e) => e.preventDefault()}
onClick={() => bold.execute()}
disabled={!bold.isEnabled}
data-active={bold.isActive || undefined}
title={bold.disabledReason ?? 'Bold'}
>
B
</button>
);
}| Field | Type | Description |
|---|---|---|
execute() | () => boolean | Runs the command and reports whether it applied. |
isActive | boolean | Reports the command state at the caret. |
isEnabled | boolean | Reports whether the command can run. |
disabledReason | string | null | Explains why the command cannot run. |
Use isEnabled as the enabled-state source.
Use disabledReason when you explain a disabled control.
Pass an EditorCommand when no chrome slot matches your action:
const suggest = useEditorCommand({ type: 'setEditingMode', mode: 'suggesting' });useEditorState
Use useEditorState to subscribe to part of the editor snapshot.
The hook runs the selector for each state update.
It renders your component only when the selected value changes:
import { useEditorState } from '@docx-editor.dev/react';
function PageIndicator() {
const page = useEditorState((s) => s.page);
return (
<span>
{page.current} / {page.total}
</span>
);
}
function SaveButton() {
const dirty = useEditorState((s) => s.canUndo ?? false);
return <button disabled={!dirty}>Save</button>;
}Pass a comparison function as the second argument for object values:
const formatting = useEditorState(
(s) => s.formatting,
(a, b) => a?.bold === b?.bold && a?.italic === b?.italic
);Select only the state that your component needs. A page indicator does not need to render after a bold-state change.
Useful fields include:
pageselectionandselectionCollapsedformattingtableandimageeditableisLoadingandisOpeningparseErroreditingModecanUndoandcanRedopageSetupfontSubstitutionshasReviewContentlastRejection
useDocxEditor
useDocxEditor returns the editor instance.
It returns null before the DocxEditor.Root mount effect creates the
instance.
It also returns null outside a DocxEditor.Root.
Use the instance for actions and one-time reads:
import { useDocxEditor } from '@docx-editor.dev/react';
function SaveButton() {
const editor = useDocxEditor();
return (
<button
disabled={!editor}
onClick={async () => {
const bytes = await editor?.save();
if (bytes) void upload(bytes);
}}
>
Save
</button>
);
}Calling editor.snapshot() during render does not subscribe your component.
Use useEditorState for reactive state.
useEditorEvent
Use useEditorEvent to subscribe for the component's lifetime:
import { useEditorEvent } from '@docx-editor.dev/react';
useEditorEvent('selectionChange', () => setPanelOpen(false));
useEditorEvent('change', (change) => void autosave(change.revision));useFontFamily
useFontFamily provides font-picker state.
It returns the current value, options, setter, and enabled state:
import { useFontFamily } from '@docx-editor.dev/react';
function FontPicker() {
const font = useFontFamily();
return (
<select
value={font.value ?? ''}
disabled={!font.isEnabled}
onChange={(e) => font.setValue(e.target.value)}
>
{font.options.map((family) => (
<option key={family} value={family}>
{family}
</option>
))}
</select>
);
}useParagraphStyle returns the same shape for paragraph styles.
usePageSetup
Use usePageSetup to read and change the current section.
The hook supports margins, orientation, and paper size:
import { usePageSetup } from '@docx-editor.dev/react';
function OrientationToggle() {
const { pageSetup, apply, isEnabled } = usePageSetup();
const landscape = pageSetup?.orientation === 'landscape';
return (
<button
disabled={!isEnabled}
onClick={() => apply({ orientation: landscape ? 'portrait' : 'landscape' })}
>
{landscape ? 'Portrait' : 'Landscape'}
</button>
);
}useParagraphFormat
Use useParagraphFormat to read and change the paragraph at the selection.
apply sends the supplied fields as one command, so one call creates one undo
step:
import { useParagraphFormat } from '@docx-editor.dev/react';
function DoubleSpaceButton() {
const { format, apply, isEnabled } = useParagraphFormat();
const isDouble = format?.lineSpacing?.value === 2;
return (
<button
disabled={!isEnabled}
onClick={() => apply({ lineSpacing: { rule: 'multiple', value: isDouble ? 1 : 2 } })}
>
{isDouble ? 'Single space' : 'Double space'}
</button>
);
}A field is null when selected paragraphs have different values. A checkbox
shows an indeterminate state. A number field has no indeterminate state. It shows
a default until you change it. Omitted fields are not written, so existing values
stay. Spacing, line-spacing, and indent fields also accept null. That value
clears the local setting so the style supplies it. Writing 0 sets an explicit
value instead.
For the whole form, DocxEditor.ParagraphDialog is the Paragraph dialog
over this hook.
useDocumentOutline
useDocumentOutline returns headings in document order.
It also provides an action that moves to a heading:
import { useDocumentOutline } from '@docx-editor.dev/react';
function Outline() {
const { items, selectedBlockId, goTo, isEmpty } = useDocumentOutline();
if (isEmpty) return <p>No headings</p>;
return (
<ul>
{items.map(({ heading, depth }) => (
<li key={heading.blockId} style={{ paddingLeft: depth * 12 }}>
<button
data-active={heading.blockId === selectedBlockId || undefined}
onClick={() => goTo(heading.blockId)}
>
{heading.text}
</button>
</li>
))}
</ul>
);
}Each item has the shape { heading, depth }.
heading has the shape { text, level, blockId }.
depth measures indentation from the shallowest heading in the document.
This calculation aligns a top-level Heading 2 with the base.
Use headings when you need the flat list without calculated indentation.
useDocumentSearch
useDocumentSearch provides delayed search and match navigation:
import { useDocumentSearch } from '@docx-editor.dev/react';
function Find() {
const search = useDocumentSearch();
return (
<>
<input value={search.query} onChange={(event) => search.setQuery(event.target.value)} />
<span>
{search.matches.length === 0 ? 0 : search.activeIndex + 1}
{' / '}
{search.matches.length}
{search.truncated && '+'}
</span>
<button onClick={search.previous}>Prev</button>
<button onClick={search.next}>Next</button>
</>
);
}The result also includes these pairs:
matchCaseandsetMatchCasewholeWordandsetWholeWord
Other hooks
| Hook | Return value |
|---|---|
useDocxSource(source, options?) | Fetches bytes and fonts for a URL, File, or Blob. It supports cancellation. |
useEditorValueCommand(slotId) | Provides state for value commands such as 'image.wrap' and 'image.altText'. |
useParagraphIndent() | Provides current indents and an apply action. |
useHyperlinkPopup() | Provides state for a custom hyperlink panel. |
useContentControl() | Provides content-control locks, value writes, and form-fill state. |
useHeaderFooterState() | Returns the active header or footer scope, or null. |
useNoteScopeState() | Returns the active footnote or endnote scope. |
useContextMenuTarget() | Returns the element that received the last context-menu action. |
useNavigationPane(options?) | Provides navigation-pane open state and width. |
useTranslation() | Returns { t } for the active locale catalog. |
useChromeTranslate(overrides?) | Returns a catalog resolver that checks an override Map first. |
useFonts(source, ...fragments) | Builds a stable FontResolver. See the Fonts guide. |
useNotePropertiesState() | Provides note-numbering properties for the current scope. |
useEditorSnapshot(editor) | Returns a revision counter for useSyncExternalStore. |
useNavigationShift() | Returns the horizontal offset for an open navigation pane. |
useReviewGutter() | Returns the inline reservations for the active review rail. |
useTableBorderTargetLabel() | Returns the active table-border target label. |
useReviewAuthors() | Returns tracked-change authors, then comment-only authors. Each item includes its resolved style. |
useEditorCaret() | Returns { paragraphId, offset } for APIs that accept an at position. |
useZoom() | Reads and sets zoom from custom chrome. |
useToolbarContext() | Returns toolbar compound context for custom slot parts. |
useToolbarLabel() | Returns the active toolbar-scope label. |
useToolbarLabelFor(slotId) | Resolves the label for one slot ID. |
useScopeClassName() | Returns the scoped chrome class prefix. |
useScopedChromeAnchor() | Returns anchor metadata for scoped overlay chrome. |
Use useContentControlInstance() outside the owning content-control part.
Use useHyperlinkPopupInstance() outside the owning hyperlink part.
These hooks provide context-free variants of the corresponding hooks.
@docx-editor.dev/pro/react provides useReview,
useReviewOf, useReviewItem, and useReviewAuthor.
@docx-editor.dev/pro/vue provides the Vue equivalents.