返回 presentation-ai
usePlateEditor.ts
根目录 / src / components / plate / hooks / usePlateEditor.ts
1 import { MarkdownPlugin } from "@platejs/markdown";
2 import { type Value } from "@platejs/slate";
3 import { type AnyPluginConfig } from "platejs";
4 import {
5 createPlateEditor,
6 type CreatePlateEditorOptions,
7 type PlateEditor,
8 } from "platejs/react";
9 import React from "react";
10
11 /**
12 * Creates a memoized Plate editor for React components.
13 *
14 * This hook creates a fully configured Plate editor instance that is memoized
15 * based on the provided dependencies. It's optimized for React components to
16 * prevent unnecessary re-creation of the editor on every render.
17 *
18 * Examples:
19 *
20 * ```ts
21 * const editor = usePlateEditor({
22 * plugins: [ParagraphPlugin, HeadingPlugin],
23 * value: [{ type: 'p', children: [{ text: 'Hello world!' }] }],
24 * });
25 *
26 * // Editor with custom dependencies
27 * const editor = usePlateEditor(
28 * {
29 * plugins: [ParagraphPlugin],
30 * enabled,
31 * },
32 * [enabled]
33 * ); // Re-create when enabled changes
34 * ```
35 *
36 * @param options - Configuration options for creating the Plate editor
37 * @param deps - Additional dependencies for the useMemo hook (default: [])
38 * @see {@link createPlateEditor} for detailed information on React editor creation and configuration.
39 * @see {@link createSlateEditor} for a non-React version of editor creation.
40 * @see {@link withPlate} for the underlying React-specific enhancement function.
41 */
42 export function usePlateEditor(
43 options: CreatePlateEditorOptions<Value, AnyPluginConfig> & {
44 enabled?: boolean;
45 initialMarkdown?: string;
46 } = {},
47 deps: React.DependencyList = [],
48 ): ReturnType<typeof createPlateEditor> {
49 const [, forceRender] = React.useState({});
50 const isMountedRef = React.useRef(false);
51
52 React.useEffect(() => {
53 isMountedRef.current = true;
54 return () => {
55 isMountedRef.current = false;
56 };
57 }, []);
58
59 const value: CreatePlateEditorOptions<Value, AnyPluginConfig>["value"] =
60 !options.initialMarkdown
61 ? options.value
62 : (editor: PlateEditor) =>
63 editor
64 .getApi(MarkdownPlugin)
65 .markdown.deserialize(options.initialMarkdown ?? "", {
66 withoutMdx: true,
67 });
68
69 return React.useMemo(() => {
70 const editor = createPlateEditor({
71 ...options,
72 value: value,
73 onReady: (ctx) => {
74 if (ctx.isAsync && isMountedRef.current) {
75 forceRender({});
76 }
77 options.onReady?.(ctx);
78 },
79 });
80
81 return editor;
82 }, [options.id, options.enabled, ...deps]);
83 }
84
84 lines TYPESCRIPT