Plate Controller

PlateController 组件的 API 参考。

PlateController 是一个可选的 provider 组件,用于从各自的 Plate 组件外部访问特定的 Plate Stores

PlateController Store

PlateController Store 包含基于 id 获取 Plate Store 以及确定当前活动 id 所需的信息。

State

Collapse all

    最近获得焦点的 Plate 编辑器的 id

    • 默认值: null

    所有主要 Plate 编辑器的 id。默认情况下,除非向其 Plate 组件传递了 primary={false},否则编辑器被视为主要编辑器。

    • 默认值: []

    从每个已挂载的 Plate 编辑器的 id 到该编辑器的 Plate Store 对应的 JotaiStore 的映射。

    • 默认值: {}

使用模式

通过 ID 访问特定编辑器

PlateController 可用于使用其 id 访问特定编辑器的 store。请注意,如果找不到匹配的编辑器,将返回一个不可变的回退编辑器。

const App = withHoc(PlateController, () => {
  const mainEditor = useEditorRef('main');
  
  useEffect(() => {
    if (!mainEditor.isFallback) {
      console.info('Editor mounted', mainEditor);
    }
  }, [mainEditor]);
  
  return (
    <>
      <Plate editor={createPlateEditor({ id: 'main' })}>
        <PlateContent />
      </Plate>
    
      <Plate editor={createPlateEditor({ id: 'secondary' })}>
        <PlateContent />
      </Plate>
    </>
  );
});

活动编辑器

如果在 PlateController 内部使用 useEditorRef 等钩子时没有显式指定 id,它们将解析为当前活动的编辑器。

活动编辑器的确定方式如下:

  1. 如果某个编辑器已获得焦点,则返回最后一个这样的编辑器。
  2. 如果某个编辑器是主要编辑器,则返回第一个挂载的这样的编辑器。
  3. 否则,返回一个不可变的回退编辑器。
const App = withHoc(PlateController, () => {
  const activeEditorId = useEditorId();
  const isFallback = !useEditorMounted();
  
  const message = isFallback
    ? '请聚焦一个编辑器'
    : `活动编辑器:${activeEditorId}`;
  
  return (
    <main>
      <p>{message}</p>
      
      <Plate editor={createPlateEditor({ id: 'main', primary: false })}>
        <PlateContent />
      </Plate>
    
      <Plate editor={createPlateEditor({ id: 'secondary', primary: false })}>
        <PlateContent />
      </Plate>
    </main>
  );
});

处理回退编辑器

当在 PlateController 内部调用的钩子无法找到匹配的 Plate Store 时,它将使用 Plate Store 的默认值。editor 的默认值是 createPlateFallbackEditor()。回退编辑器就像一个没有插件的空 Plate 编辑器,但如果它收到 Slate 操作,则会抛出运行时错误(即它是不可变的,不能用于转换)。

这样做的原因是确保查询编辑器的代码(例如确定工具栏按钮是否处于活动状态)在出现问题时静默失败并返回合理的默认值,而转换编辑器的代码(例如按下工具栏按钮)则大声失败并显示错误。

有两种方法可以确定您是否正在使用回退编辑器或真实编辑器:

  • useEditorMounted 如果无法解析到已挂载的编辑器,则返回 false
  • editor.meta.isFallback 对于回退编辑器为 true

PlateController 内部使用 useEditorRef 等钩子时,您应该编写防御性代码,以确保在出现回退编辑器时能够适当处理。例如,如果 useEditorMounted 返回 false,您可以禁用工具栏按钮,或者如果 editor.meta.isFallbacktrue,则可以忽略事件。

import { KEYS } from 'platejs';
 
const App = withHoc(PlateController, () => {
  const activeEditor = useEditorRef();
  
  const toggleBold = () => {
    if (activeEditor.isFallback) return;
    activeEditor.tf.toggleMark(KEYS.bold);
  };
  
  return (
    <main>
      <button type="button" onClick={toggleBold}>
        Bold
      </button>
      
      <Plate editor={createPlateEditor({ id: 'main', primary: false })}>
        <PlateContent />
      </Plate>
    
      <Plate editor={createPlateEditor({ id: 'secondary', primary: false })}>
        <PlateContent />
      </Plate>
    </main>
  );
});
const App = withHoc(PlateController, () => {
  const activeEditor = useEditorRef();
  const isFallback = !useEditorMounted();
  
  const toggleBold = () => {
    activeEditor.tf.toggleMark(KEYS.bold);
  };
  
  return (
    <main>
      <button
        type="button"
        onClick={toggleBold}
        disabled={isFallback}
      >
        Bold
      </button>
      
      <Plate editor={createPlateEditor({ id: 'main', primary: false })}>
        <PlateContent />
      </Plate>
    
      <Plate editor={createPlateEditor({ id: 'secondary', primary: false })}>
        <PlateContent />
      </Plate>
    </main>
  );
});