EditorApi

EditorApi exposes React Editor’s internals to enable extension and modification to React Editor’s core behavior. It can be accessed by the useEditor and useGetEditor hooks.

EditorApi can currently only be accessed through composition, UI overrides or custom fields.

Params

ParamExampleType
appState{ data: {}, ui: {} }AppState
dispatch(action: EditorAction) => voidFunction
getItemBySelector() => ({ type: "Heading", props: {} })Function
getItemById() => ({ type: "Heading", props: {} })Function
getSelectorForId() => ({ index: 0, zone: 'Flex-123:children' })Function
getPermissions() => ({ delete: true })Function
history{}Object
refreshPermissions() => voidFunction
resolveDataById() => voidFunction
resolveDataBySelector() => voidFunction
selectedItem{ type: "Heading", props: {id: "my-heading"} }ComponentData

appState

The current application state for this React Editor instance.

console.log(appState.data);
// { content: [], root: {}, zones: {} }

dispatch(action)

Execute an action to mutate the React Editor application state.

dispatch({
  type: "setUi",
  ui: {
    leftSideBarVisible: false,
  },
});

getItemBySelector(selector)

Get an item’s ComponentData by its selector.

getItemBySelector({
  index: 0,
  zone: "Flex-123:children", // The "children" slot field in the component with id "Flex-123"
});
// { type: "HeadingBlock", props: {} }

getItemById(id)

Get an item’s ComponentData by its component id.

getItemById("HeadingBlock-123");
// { type: "HeadingBlock", props: {} }

getParentById(id)

Get an item’s parent ComponentData using the child component’s ID.

getSelectorForId(id)

Get an item’s selector by its component id.

getSelectorForId("HeadingBlock-123");
// { index: 0, zone: "Flex-123:children" }

getPermissions(params)

Get global, component or resolved dynamic permissions.

getPermissions();
// { delete: true, edit: true }

Params

ParamExampleType
item{ type: "HeadingBlock", props: { id: "1234" } }Object
rootfalseBoolean
type"HeadingBlock"String
item

Specify item to retrieve the permissions for a given component instance, resolving any dynamic permissions for that component, as set by the resolvePermissions parameter.

getPermissions({
  item: { type: "HeadingBlock", props: { id: "Heading-1234" } }, // Get resolved permissions for Heading-1234
});
// { delete: false }

The getPermissions function will be redefined when after resolving dynamic permissions, so it’s generally required to wrap it in a useEffect hook:

const [myPermissions, setMyPermissions] = useState(getPermissions());
 
useEffect(() => {
  setMyPermissions(getPermissions());
}, [getPermissions]);
root

Specify root to retrieve the permissions for the root, as set by the permissions parameter.

getPermissions({ root: true });
// { delete: false }
type

Specify type to retrieve the permissions for a given component type, as set by the permissions parameter.

getPermissions({ type: "HeadingBlock" });
// { delete: false }

history

The history API provides programmatic access to the undo/redo AppState history.

ParamExampleType
back() => voidFunction
forward() => voidFunction
hasPasttrueBoolean
hasFuturefalseBoolean
histories[{ id: 'abc123', data: {} }]History[]
index5Number
setHistoriessetHistories: (histories) => voidFunction
setHistoryIndexsetHistoryIndex: (index) => voidFunction

history.back()

A function to move the app state back through the histories.

history.forward()

A function to move the app state forward through the histories.

history.hasPast

A boolean describing whether or not the present app state has past history items.

history.hasFuture

A boolean describing whether or not the present app state has future history items.

history.histories

An array describing the recorded history as History objects.

History params
ParamExampleType
state{}AppState
idabc123String
state

The app state payload for this history entry.

id

An optional ID for this history entry.

history.index

The index of the currently selected history in history.histories

setHistories

A function to set the history state.

setHistories([]); // clears all history

setHistoryIndex

A function to set current history index.

setHistoryIndex(2);

refreshPermissions(params)

Force the permissions to refresh, running all resolvePermissions functions and skipping the cache.

resolvePermissions(); // Refresh all permissions

Params

ParamExampleType
item{ type: "HeadingBlock", props: { id: "1234" } }Object
rootfalseBoolean
type"HeadingBlock"String
item

Specify item to refresh the permissions for a given component instance only.

refreshPermissions({
  item: { type: "HeadingBlock", props: { id: "Heading-1234" } }, // Force refresh the resolved permissions for Heading-1234
});
root

Specify root to refresh the permissions for the root only.

refreshPermissions({ root: true });
type

Specify type to refresh the permissions for all components of a given component type.

refreshPermissions({ type: "HeadingBlock" });

resolveDataById(id, trigger)

Runs a component’s resolveData by id for a given trigger.

resolveDataById("Heading-1234", "replace");

resolveDataBySelector(selector, trigger)

Runs a component’s resolveData by selector for a given trigger.

resolveDataBySelector({ zone: "Flex-1234:items", index: 0 }, "insert");

selectedItem

The currently selected item, as defined by appState.ui.itemSelector.

console.log(selectedItem);
// { type: "Heading", props: {id: "my-heading"} }

Commands

Higher-level mutation helpers that wrap dispatch for common operations. Each command resolves the target by id and is a no-op if the id isn’t found in the tree.

Accessing commands

Commands live on the EditorApi returned by useEditor (inside render) or useGetEditor (inside callbacks and effects). Both hooks must be called from a component rendered inside <Editor> — typically through composition, UI overrides, or custom fields.

import { useGetEditor } from "@reacteditor/core";
 
const RenameButton = () => {
  const getEditor = useGetEditor();
 
  return (
    <button
      onClick={() => {
        const editor = getEditor();
        const id = editor.selectedItem?.props.id;
        if (id) editor.updateProps(id, { children: "Renamed" });
      }}
    >
      Rename selected
    </button>
  );
};

For UI that must re-render when the editor state changes, use useEditor with a selector:

import { createUseEditor } from "@reacteditor/core";
 
const useEditor = createUseEditor();
 
const PropEditor = () => {
  const selected = useEditor((s) => s.selectedItem);
  const updateProps = useEditor((s) => s.updateProps);
 
  if (!selected) return null;
 
  return (
    <input
      value={selected.props.children ?? ""}
      onChange={(e) => updateProps(selected.props.id, { children: e.target.value })}
    />
  );
};
CommandExampleReturns
insertComponentinsertComponent({ type: "Heading" }){ id: string }
removeComponentremoveComponent("Heading-123")void
duplicateComponentduplicateComponent("Heading-123")void
moveComponentmoveComponent("Heading-123", { index: 2 })void
replaceComponentreplaceComponent("Heading-123", data)void
updatePropsupdateProps("Heading-123", { size: "lg" })void
updateRootupdateRoot({ title: "Home" })void
selectComponentselectComponent("Heading-123")void
scrollToComponentscrollToComponent("Heading-123")void

insertComponent(args)

Insert a new component into the tree. Returns the id of the inserted component.

const { id } = insertComponent({
  type: "HeadingBlock",
  parent: { id: "Flex-123", slot: "items" },
  index: 0,
  data: { type: "HeadingBlock", props: { id: "", children: "Hello" } },
  select: true,
});

Args

ParamExampleTypeStatus
typetype: "HeadingBlock"StringRequired
parentparent: { id: "Flex-123", slot: "items" }{ id: string; slot: string }Defaults to the root drop zone
indexindex: 0NumberDefaults to the end of the target zone
datadata: { type: "HeadingBlock", props: { children: "" }}ComponentDataDefaults to a new component with defaultProps
selectselect: falseBooleanDefaults to true — auto-selects the inserted component

removeComponent(id)

Remove the component with the given id from the tree.

removeComponent("HeadingBlock-1234");

duplicateComponent(id)

Duplicate the component with the given id, inserting the copy immediately after it.

duplicateComponent("HeadingBlock-1234");

moveComponent(id, to)

Move the component to a different position or zone.

moveComponent("HeadingBlock-1234", {
  parent: { id: "Flex-123", slot: "items" },
  index: 0,
});

to params

ParamExampleTypeStatus
parentparent: { id: "Flex-123", slot: "items" }{ id: string; slot: string }Defaults to the root drop zone
indexindex: 2NumberRequired

replaceComponent(id, data)

Replace the component’s data while preserving its existing id and position.

replaceComponent("HeadingBlock-1234", {
  type: "HeadingBlock",
  props: { children: "Replaced" },
});

updateProps(id, updater)

Patch a component’s props. Pass an object to merge keys, or a function that receives the previous props and returns a partial.

// Object form — merge
updateProps("HeadingBlock-1234", { size: "lg" });
 
// Function form — read previous props
updateProps("HeadingBlock-1234", (prev) => ({
  count: (prev.count ?? 0) + 1,
}));

The component’s id is preserved regardless of what the updater returns.

updateRoot(updater)

Patch the root props. Same shape as updateProps.

updateRoot({ title: "Home" });
updateRoot((prev) => ({ visited: (prev.visited ?? 0) + 1 }));

selectComponent(id)

Select the component with the given id, or pass null to clear the selection.

selectComponent("HeadingBlock-1234");
selectComponent(null); // clear selection

scrollToComponent(id)

Scroll the preview canvas so the component with the given id is in view.

scrollToComponent("HeadingBlock-1234");