Loading...
Loading...
@suneditor/suneditor-react is the official React component. Every editor option passes through unchanged, and the engine loads on the client only, so it works in Next.js without next/dynamic.
This page is the package README of the installed version, translated. The Playground and Getting Started emit code for the same version.
The component needs the SunEditor engine as well (peer dependency, 3.4.1 or later)
npm install suneditor @suneditor/suneditor-reactimport SunEditor from '@suneditor/suneditor-react';
import 'suneditor/css/editor';
import 'suneditor/css/contents';
export default function App() {
return (
<SunEditor
options={(se) => ({
plugins: [se.plugins.link, se.plugins.image, se.plugins.table],
buttonList: [
['undo', 'redo'],
['bold', 'italic', 'underline'],
['table', 'link', 'image'],
],
height: '400px',
})}
/>
);
}options is handed to suneditor.create() as-is, so every option, plugin, button, event and language is the engine's own.
This README covers only what the React component adds; for the options themselves see the SunEditor documentation or the suneditor package.
options receives the lazily loaded suneditor module (se.plugins, se.langs, se.interfaces, ...).
Prefer this form in Next.js: importing suneditor statically in a client component breaks server rendering because the engine touches window at import time.
A plain object also works when you are not server rendering, or for options that need no engine import.
Language packs are plain objects and can always be imported statically: import ko from 'suneditor/langs/ko'.
const [html, setHtml] = useState('<p>Hello</p>');
<SunEditor value={html} onChange={setHtml} options={...} />Changing value to something other than the last onChange result replaces the editor content.
Omit value for an uncontrolled editor and read the content from the instance when you need it.
const ref = useRef<SunEditorInstance | null>(null);
<SunEditor ref={ref} options={...} />
ref.current?.$.html.get();
ref.current?.$.html.set('<p>new</p>');
ref.current?.resetOptions({ height: '600px' });ref is the object returned by suneditor.create(), so the whole engine API is available.
Pass handlers through options.events. They are re-synced on every render, so they can safely close over React state.
<SunEditor
options={(se) => ({
plugins: [se.plugins.image],
events: {
onSave: async () => { await save(html); return true; },
onImageUploadBefore: ({ info, handler }) => { ... },
},
})}
/>Engine options that take a DOM element work with refs because the options function runs after mount:
const toolbarRef = useRef<HTMLDivElement>(null);
<div ref={toolbarRef} />
<SunEditor options={(se) => ({ plugins: [se.plugins.link], toolbar_container: toolbarRef.current })} />One engine instance (toolbar, plugins, events, theme) with several editable areas. Put a <SunEditorRoot> per area inside <SunEditorGroup>; any other JSX can sit between them. The group renders no element of its own.
const toolbarRef = useRef<HTMLDivElement>(null);
<SunEditorGroup options={(se) => ({ plugins: [se.plugins.link], toolbar_container: toolbarRef.current })}>
<div ref={toolbarRef} />
<h2>Title</h2>
<SunEditorRoot name='header' value={header} onChange={setHeader} options={{ height: '80px' }} />
<SunEditorRoot name='body' value={body} onChange={setBody} readOnly={locked} />
</SunEditorGroup>;name is the engine rootKey (ref.current.changeFrameContext('body'), html.get({ rootKey: 'body' })).value / onChange, readOnly, disabled and frame options (height, placeholder, iframe, ...).toolbar_container for the shared toolbar unless mode is inline or balloon.key to recreate it with different roots.| Prop | Type | Description |
|---|---|---|
value | string | Editor HTML (controlled). |
onChange | (html: string) => void | Called on every content change. Shorthand for options.events.onChange. |
options | SunEditorOptions | (se) => SunEditorOptions | SunEditor options, passed through unchanged. events and theme are applied live. Everything else is applied once at creation. |
readOnly | boolean | Toggle read-only mode. |
disabled | boolean | Disable the editor. |
className, style | Applied to the wrapping <div>. | |
...divProps | HTMLAttributes<HTMLDivElement> | Any other prop (id, data-*, aria-*, ...) is applied to the wrapping <div>. children is ignored. |
ref | SunEditorInstance | null | The editor instance. |
Options other than events and theme are applied when the editor is created.
To change them later, remount with a different key or call ref.current.resetOptions().
import type {
SunEditorProps,
SunEditorGroupProps,
SunEditorRootProps,
SunEditorInstance,
SunEditorOptions,
SunEditorFrameOptions,
SunEditorEvents,
} from '@suneditor/suneditor-react';All engine types are also available from suneditor/types.
"use client" is in the build output) and loads the engine only in the browser, so it can be rendered from a server component directly.suneditor out of static imports in client components. Use the options={(se) => ...} form to reach se.plugins.suneditor/css/editor, suneditor/css/contents, suneditor/src/themes/*.css) work in both the App Router and the Pages Router.