{"record":{"id":"25b79ebc44d5d119","repo":"ianstormtaylor/slate","slug":"the-useslate-hook-must-be-used-inside-the-slate","errorCode":null,"errorMessage":"The `useSlate` hook must be used inside the <Slate> component's context.","messagePattern":"The `useSlate` hook must be used inside the <Slate> component's context\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slate-react/src/hooks/use-slate.tsx","lineNumber":16,"sourceCode":"import { MutableRefObject, useContext, useMemo, useReducer } from 'react'\nimport { Editor } from 'slate'\nimport { SlateSelectorContext } from './use-slate-selector'\nimport { useSlateStatic } from './use-slate-static'\nimport { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect'\n\n/**\n * Get the current editor object and re-render whenever it changes.\n */\n\nexport const useSlate = (): Editor => {\n  const { addEventListener } = useContext(SlateSelectorContext)\n  const [, forceRender] = useReducer(s => s + 1, 0)\n\n  if (!addEventListener) {\n    throw new Error(\n      `The \\`useSlate\\` hook must be used inside the <Slate> component's context.`\n    )\n  }\n\n  useIsomorphicLayoutEffect(\n    () => addEventListener(forceRender),\n    [addEventListener]\n  )\n\n  return useSlateStatic()\n}\n\nconst EDITOR_TO_V = new WeakMap<Editor, MutableRefObject<number>>()\n\nconst getEditorVersionRef = (editor: Editor): MutableRefObject<number> => {\n  let v = EDITOR_TO_V.get(editor)\n\n  if (v) {","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/ianstormtaylor/slate/blob/72a37c701e5da4bb13a305d416d9c070d19d3a45/packages/slate-react/src/hooks/use-slate.tsx#L1-L34","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Move the offending component inside the <Slate editor={editor}> tree so the context is available.","If the component cannot live inside <Slate>, pass the editor as a prop (or use the withReact editor instance you created) instead of useSlate().","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.","In tests, wrap the component with <Slate editor={editor} initialValue={...}> (and the editor created with withReact(createEditor())).","Ensure only one copy of slate-react and React is installed (dedupe node_modules) so the imported SlateSelectorContext matches the provider's."],"exampleFix":"// before\nfunction Toolbar() {\n  const editor = useSlate() // throws: outside <Slate>\n  return <button onClick={() => toggleMark(editor, 'bold')}>B</button>\n}\nexport function App() {\n  return <>\n    <Slate editor={editor} initialValue={initialValue}>\n      <Editable />\n    </Slate>\n    <Toolbar />\n  </>\n}\n\n// after\nexport function App() {\n  return (\n    <Slate editor={editor} initialValue={initialValue}>\n      <Editable />\n      <Toolbar />\n    </Slate>\n  )\n}","handlingStrategy":"validation","validationCode":"// Check context presence before calling useSlate (test/dev guard)\nimport { SlateContext } from 'slate-react'\n// In a parent: const ctx = useContext(SlateContext)\n// if (!ctx) render the component with editor passed as prop instead","typeGuard":"// Runtime guard for wrapping components that optionally support Slate context\nfunction useOptionalSlate(): Editor | null {\n  const ctx = React.useContext(SlateContext)\n  return ctx ?? null\n}","tryCatchPattern":null,"preventionTips":["Always render editing-related components (toolbars, menus, balloons) as children of <Slate>.","Pass the editor instance as a prop to components that must live outside the Slate tree.","In tests, always mount with a <Slate editor={withReact(createEditor())} initialValue={...}> wrapper.","Run npm ls slate-react react to verify a single copy of each before debugging context issues."],"tags":["react","context","hooks","slate","provider"],"backgroundTag":null,"analyzedSha":"72a37c701e5da4bb13a305d416d9c070d19d3a45","analyzedAt":"2026-08-27T23:04:51.145Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}