Editor

The Editor class is the main way of controlling tldraw's editor. You can use it to manage the editor's internal state, make changes to the document, or respond to changes that have occurred.

By design, the editor's surface area is very large. Almost everything is available through it. Need to create some shapes? Use Editor.createShapes. Need to delete them? Use Editor.deleteShapes. Need a sorted array of every shape on the current page? Use Editor.getCurrentPageShapesSorted.

Accessing the editor

You can access the editor in two ways:

The onMount callback

The Tldraw component's onMount callback provides the editor as the first argument.

function App() {
	return (
		<Tldraw
			onMount={(editor) => {
				// your editor code here
			}}
		/>
	)
}

The useEditor hook

The useEditor hook returns the editor instance. Call it from a component rendered inside Tldraw (or TldrawEditor).

function InsideOfContext() {
	const editor = useEditor()
	// your editor code here
	return null
}

function App() {
	return (
		<Tldraw>
			<InsideOfContext />
		</Tldraw>
	)
}

If you're using the subcomponents as shown in this example, the editor instance is provided by the TldrawEditor component.

Reactive state

The editor's state is reactive. Methods like Editor.getSelectedShapeIds or Editor.getCurrentPageShapes return values that automatically update when the underlying data changes. You can use these values directly in React components with the track wrapper or useValue hook.

import { track, useEditor, useValue } from 'tldraw'

export const SelectedShapeIdsCount = track(() => {
	const editor = useEditor()
	return <div>{editor.getSelectedShapeIds().length}</div>
})

export function CurrentTool() {
	const editor = useEditor()
	const toolId = useValue('current tool', () => editor.getCurrentToolId(), [editor])
	return <div>{toolId}</div>
}

See the Signals article for more on tldraw's reactive state system.

Batching changes

Each change to the editor happens within a transaction. You can batch multiple changes into a single transaction using the Editor.run method. Batching groups the changes into a single undo step and reduces overhead for persisting or distributing changes.

// myShapes is an array of shape partials, each with an id from createShapeId()
editor.run(() => {
	editor.createShapes(myShapes)
	editor.sendToBack(myShapes.map((shape) => shape.id))
	editor.selectNone()
})

The run method also accepts options to control history and locked shape behavior. Set history to 'ignore' to leave undo/redo alone, or 'record-preserveRedoStack' to record without clearing the redo stack:

// Make changes without affecting undo/redo history
editor.run(
	() => {
		editor.createShapes(myShapes)
	},
	{ history: 'ignore' }
)

// Make changes to locked shapes
editor.run(
	() => {
		editor.updateShapes(myLockedShapes)
	},
	{ ignoreShapeLock: true }
)

Capabilities

The editor's methods and properties are organized around these areas:

AreaTopicDescription
DataSignalsReactive state primitives
StoreThe reactive database holding all records
ShapesCreate, read, update, and delete shapes
BindingsRelationships between shapes
PagesManage document pages
AssetsImages, videos, and other media
InteractionToolsThe state machine that handles user input
SelectionManage which shapes are selected
Input handlingPointer and keyboard state
EventsSubscribe to user interactions and state changes
ViewCameraControl viewport position and zoom
CoordinatesConvert between screen and page space
StateInstance statePer-editor settings like current tool and focus
VisibilityControl which shapes are shown
HistoryUndo, redo, and history management
Side effectsReact to record lifecycle changes
ConfigurationUser preferencesCross-instance settings like dark mode
Readonly modeDisable editing
Locked shapesPrevent changes to specific shapes
OutputImage exportExport to SVG, PNG, and other formats

See the Editor API reference for the complete list of methods and properties.

Prev
v2.0.0
Next
Shapes