ianstormtaylor/slate · error · Error

The `useSlate` hook must be used inside the <Slate> componen

Error message

The `useSlate` hook must be used inside the <Slate> component's context.

What it means

This error is thrown by Slate.js's useSlate hook when it is called outside of a <Slate> provider component. useSlate relies on React's useContext(SlateSelectorContext) to access the editor instance and subscribe to its changes; when the context is absent (no <Slate> ancestor), addEventListener is undefined and the hook throws immediately to fail fast rather than silently returning a broken editor.

Source

Thrown at packages/slate-react/src/hooks/use-slate.tsx:16

import { MutableRefObject, useContext, useMemo, useReducer } from 'react'
import { Editor } from 'slate'
import { SlateSelectorContext } from './use-slate-selector'
import { useSlateStatic } from './use-slate-static'
import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect'

/**
 * Get the current editor object and re-render whenever it changes.
 */

export const useSlate = (): Editor => {
  const { addEventListener } = useContext(SlateSelectorContext)
  const [, forceRender] = useReducer(s => s + 1, 0)

  if (!addEventListener) {
    throw new Error(
      `The \`useSlate\` hook must be used inside the <Slate> component's context.`
    )
  }

  useIsomorphicLayoutEffect(
    () => addEventListener(forceRender),
    [addEventListener]
  )

  return useSlateStatic()
}

const EDITOR_TO_V = new WeakMap<Editor, MutableRefObject<number>>()

const getEditorVersionRef = (editor: Editor): MutableRefObject<number> => {
  let v = EDITOR_TO_V.get(editor)

  if (v) {

View on GitHub (pinned to 72a37c701e)

Solutions

  1. Move the offending component inside the <Slate editor={editor}> tree so the context is available.
  2. If the component cannot live inside <Slate>, pass the editor as a prop (or use the withReact editor instance you created) instead of useSlate().
  3. For external toolbars/portals, use useSlate() in a child of <Slate> and pass values down, or restructure so the portal's content is rendered from within the Slate subtree.
  4. In tests, wrap the component with <Slate editor={editor} initialValue={...}> (and the editor created with withReact(createEditor())).
  5. Ensure only one copy of slate-react and React is installed (dedupe node_modules) so the imported SlateSelectorContext matches the provider's.

Example fix

// before
function Toolbar() {
  const editor = useSlate() // throws: outside <Slate>
  return <button onClick={() => toggleMark(editor, 'bold')}>B</button>
}
export function App() {
  return <>
    <Slate editor={editor} initialValue={initialValue}>
      <Editable />
    </Slate>
    <Toolbar />
  </>
}

// after
export function App() {
  return (
    <Slate editor={editor} initialValue={initialValue}>
      <Editable />
      <Toolbar />
    </Slate>
  )
}
Defensive patterns

Strategy: validation

Validate before calling

// Check context presence before calling useSlate (test/dev guard)
import { SlateContext } from 'slate-react'
// In a parent: const ctx = useContext(SlateContext)
// if (!ctx) render the component with editor passed as prop instead

Type guard

// Runtime guard for wrapping components that optionally support Slate context
function useOptionalSlate(): Editor | null {
  const ctx = React.useContext(SlateContext)
  return ctx ?? null
}

Prevention

When it happens

Trigger: Calling useSlate() (directly or indirectly via useSlateWithV, useFocused, or a custom hook/component) in a component that is not rendered as a descendant of <Slate editor={editor}>. Also triggered by rendering toolbars, overlays, or portals outside the <Slate> tree, or by accessing the context in a module-level or class component where the hook runs outside the provider.

Common situations: Common with toolbars/menus rendered via React portals outside <Slate>, in unit tests (Enzyme/Jest) that shallow-render an editing component without the <Slate> wrapper, after refactoring when a component is moved out of the provider subtree, or when multiple React copies / slate-react versions cause the context instance used by the hook to differ from the one provided.

Related errors


AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27). Data as JSON: /api/errors/25b79ebc44d5d119. Report an issue: GitHub.