or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-components.mdindex.mdperformance-optimization.mdplugin-system.mdreact-hooks.mdrender-functions.md

react-hooks.mddocs/

0

# React Hooks

1

2

React hooks for accessing editor state, selection, focus, and other editor properties. These hooks provide the primary interface for interacting with Slate editors in React components and are essential for building interactive editor features.

3

4

## Capabilities

5

6

### Editor State Hooks

7

8

#### useSlate

9

10

Hook to get the current editor object and re-render the component whenever the editor changes.

11

12

```typescript { .api }

13

/**

14

* Get current editor object and re-render when it changes

15

* @returns The current editor instance

16

* @description Use this hook when your component needs to respond to editor state changes

17

*/

18

function useSlate(): Editor;

19

```

20

21

**Usage Example:**

22

23

```typescript

24

import React from 'react';

25

import { useSlate } from 'slate-react';

26

import { Editor, Transforms } from 'slate';

27

28

const BoldButton = () => {

29

const editor = useSlate();

30

31

const toggleBold = () => {

32

const isActive = Editor.marks(editor)?.bold === true;

33

if (isActive) {

34

Editor.removeMark(editor, 'bold');

35

} else {

36

Editor.addMark(editor, 'bold', true);

37

}

38

};

39

40

return (

41

<button

42

onMouseDown={(e) => {

43

e.preventDefault();

44

toggleBold();

45

}}

46

>

47

Bold

48

</button>

49

);

50

};

51

```

52

53

#### useSlateStatic

54

55

Hook to get the current editor object without triggering re-renders. Use this for event handlers and other operations that don't need to respond to editor changes.

56

57

```typescript { .api }

58

/**

59

* Get current editor object without triggering re-renders

60

* @returns The current editor instance

61

* @description Use this hook in event handlers and operations that don't need to re-render on editor changes

62

*/

63

function useSlateStatic(): Editor;

64

```

65

66

**Usage Example:**

67

68

```typescript

69

import React from 'react';

70

import { useSlateStatic } from 'slate-react';

71

import { Transforms } from 'slate';

72

73

const InsertButton = () => {

74

const editor = useSlateStatic();

75

76

const insertParagraph = () => {

77

Transforms.insertNodes(editor, {

78

type: 'paragraph',

79

children: [{ text: 'New paragraph' }]

80

});

81

};

82

83

return (

84

<button onClick={insertParagraph}>

85

Insert Paragraph

86

</button>

87

);

88

};

89

```

90

91

#### useEditor (deprecated)

92

93

Legacy hook for getting the editor object. Use `useSlateStatic` instead.

94

95

```typescript { .api }

96

/**

97

* Get current editor object (deprecated - use useSlateStatic instead)

98

* @returns The current editor instance

99

* @deprecated Use useSlateStatic instead

100

*/

101

function useEditor(): Editor;

102

```

103

104

#### useSlateWithV (deprecated)

105

106

Legacy hook that returns both editor and version counter. Use `useSlate` instead.

107

108

```typescript { .api }

109

/**

110

* Get editor object and version counter (deprecated - use useSlate instead)

111

* @returns Object with editor and version counter

112

* @deprecated Use useSlate instead

113

*/

114

function useSlateWithV(): { editor: Editor; v: number };

115

```

116

117

### Selection and Focus Hooks

118

119

#### useFocused

120

121

Hook to get the current focused state of the editor.

122

123

```typescript { .api }

124

/**

125

* Get current focused state of the editor

126

* @returns true if editor is focused, false otherwise

127

*/

128

function useFocused(): boolean;

129

```

130

131

**Usage Example:**

132

133

```typescript

134

import React from 'react';

135

import { useFocused } from 'slate-react';

136

137

const EditorStatus = () => {

138

const focused = useFocused();

139

140

return (

141

<div style={{

142

padding: '8px',

143

backgroundColor: focused ? 'lightblue' : 'lightgray'

144

}}>

145

Editor is {focused ? 'focused' : 'not focused'}

146

</div>

147

);

148

};

149

```

150

151

#### useSelected

152

153

Hook to get the current selected state of an element. Must be used within a render function.

154

155

```typescript { .api }

156

/**

157

* Get current selected state of an element

158

* @returns true if element is selected, false otherwise

159

* @description Must be used inside renderElement or similar render functions

160

*/

161

function useSelected(): boolean;

162

```

163

164

**Usage Example:**

165

166

```typescript

167

import React from 'react';

168

import { useSelected, RenderElementProps } from 'slate-react';

169

170

const CustomElement = ({ attributes, children, element }: RenderElementProps) => {

171

const selected = useSelected();

172

173

return (

174

<div

175

{...attributes}

176

style={{

177

border: selected ? '2px solid blue' : '1px solid gray',

178

padding: '8px'

179

}}

180

>

181

{children}

182

</div>

183

);

184

};

185

```

186

187

#### useSlateSelection

188

189

Hook to get the current Slate selection. Only re-renders when the selection changes, providing better performance than using `useSlate`.

190

191

```typescript { .api }

192

/**

193

* Get current slate selection (only re-renders when selection changes)

194

* @returns Current selection or null

195

* @description More performant than useSlate for selection-only operations

196

*/

197

function useSlateSelection(): BaseSelection;

198

```

199

200

**Usage Example:**

201

202

```typescript

203

import React from 'react';

204

import { useSlateSelection } from 'slate-react';

205

import { Range } from 'slate';

206

207

const SelectionInfo = () => {

208

const selection = useSlateSelection();

209

210

if (!selection) {

211

return <div>No selection</div>;

212

}

213

214

const isCollapsed = Range.isCollapsed(selection);

215

216

return (

217

<div>

218

Selection: {isCollapsed ? 'Cursor' : 'Range'} at

219

[{selection.anchor.path.join(', ')}:{selection.anchor.offset}]

220

</div>

221

);

222

};

223

```

224

225

### State Management Hooks

226

227

#### useReadOnly

228

229

Hook to get the current read-only state of the editor.

230

231

```typescript { .api }

232

/**

233

* Get current read-only state of the editor

234

* @returns true if editor is read-only, false otherwise

235

*/

236

function useReadOnly(): boolean;

237

```

238

239

**Usage Example:**

240

241

```typescript

242

import React from 'react';

243

import { useReadOnly } from 'slate-react';

244

245

const EditButton = () => {

246

const readOnly = useReadOnly();

247

248

return (

249

<button disabled={readOnly}>

250

{readOnly ? 'View Only' : 'Edit'}

251

</button>

252

);

253

};

254

```

255

256

#### useComposing

257

258

Hook to get the current composing state of the editor (useful for IME input handling).

259

260

```typescript { .api }

261

/**

262

* Get current composing state of the editor

263

* @returns true if user is composing text (e.g., with IME), false otherwise

264

*/

265

function useComposing(): boolean;

266

```

267

268

**Usage Example:**

269

270

```typescript

271

import React from 'react';

272

import { useComposing } from 'slate-react';

273

274

const ComposingIndicator = () => {

275

const composing = useComposing();

276

277

return composing ? (

278

<div style={{ color: 'orange' }}>Composing...</div>

279

) : null;

280

};

281

```

282

283

### Element Context Hooks

284

285

#### useElement

286

287

Hook to get the current element. Must be used within a `renderElement` function.

288

289

```typescript { .api }

290

/**

291

* Get current element (must be used inside renderElement)

292

* @returns The current element being rendered

293

* @throws Error if used outside of renderElement context

294

*/

295

function useElement(): Element;

296

```

297

298

#### useElementIf

299

300

Hook to get the current element, or return null if not inside `renderElement`. Safer alternative to `useElement`.

301

302

```typescript { .api }

303

/**

304

* Get current element, or return null if not inside renderElement

305

* @returns The current element being rendered, or null if not in renderElement context

306

*/

307

function useElementIf(): Element | null;

308

```

309

310

**Usage Example:**

311

312

```typescript

313

import React from 'react';

314

import { useElement, RenderElementProps } from 'slate-react';

315

316

const SmartElement = ({ attributes, children }: RenderElementProps) => {

317

const element = useElement();

318

319

// Access element properties for conditional rendering

320

const className = element.type === 'heading' ? 'heading-class' : 'paragraph-class';

321

322

return (

323

<div {...attributes} className={className}>

324

{children}

325

</div>

326

);

327

};

328

```

329

330

#### useElementIf

331

332

Hook to get the current element or null if not within a `renderElement` context.

333

334

```typescript { .api }

335

/**

336

* Get current element or null if not inside renderElement

337

* @returns The current element being rendered, or null if not in render context

338

*/

339

function useElementIf(): Element | null;

340

```

341

342

**Usage Example:**

343

344

```typescript

345

import React from 'react';

346

import { useElementIf } from 'slate-react';

347

348

const FlexibleComponent = () => {

349

const element = useElementIf();

350

351

if (element) {

352

return <div>Rendering element: {element.type}</div>;

353

}

354

355

return <div>Not in element context</div>;

356

};

357

```

358

359

## Hook Usage Patterns

360

361

### Combining Hooks for Complex UI

362

363

```typescript

364

import React from 'react';

365

import {

366

useSlate,

367

useFocused,

368

useSelected,

369

useSlateSelection,

370

RenderElementProps

371

} from 'slate-react';

372

import { Editor, Range } from 'slate';

373

374

const InteractiveElement = ({ attributes, children, element }: RenderElementProps) => {

375

const editor = useSlate();

376

const focused = useFocused();

377

const selected = useSelected();

378

const selection = useSlateSelection();

379

380

const hasTextSelection = selection && !Range.isCollapsed(selection);

381

const isActive = focused && (selected || hasTextSelection);

382

383

return (

384

<div

385

{...attributes}

386

style={{

387

border: isActive ? '2px solid blue' : '1px solid gray',

388

backgroundColor: selected ? '#f0f8ff' : 'transparent',

389

opacity: focused ? 1 : 0.7

390

}}

391

onDoubleClick={() => {

392

// Select entire element on double-click

393

const path = ReactEditor.findPath(editor, element);

394

Transforms.select(editor, path);

395

}}

396

>

397

{children}

398

</div>

399

);

400

};

401

```

402

403

### Performance Considerations

404

405

When using hooks in components that render frequently, consider performance implications:

406

407

- Use `useSlateStatic` for event handlers that don't need re-renders

408

- Use `useSlateSelection` instead of `useSlate` when only selection changes matter

409

- Memoize expensive computations with `useMemo` and `useCallback`

410

411

```typescript

412

import React, { useMemo, useCallback } from 'react';

413

import { useSlate, useSlateStatic } from 'slate-react';

414

import { Editor } from 'slate';

415

416

const OptimizedToolbar = () => {

417

const editor = useSlate(); // Re-renders on editor changes

418

const staticEditor = useSlateStatic(); // No re-renders

419

420

// Memoize expensive calculations

421

const isSelectionActive = useMemo(() => {

422

return !!editor.selection && !Range.isCollapsed(editor.selection);

423

}, [editor.selection]);

424

425

// Use static editor for event handlers

426

const handleBoldClick = useCallback(() => {

427

Editor.addMark(staticEditor, 'bold', true);

428

}, [staticEditor]);

429

430

return (

431

<div>

432

<button

433

disabled={!isSelectionActive}

434

onClick={handleBoldClick}

435

>

436

Bold

437

</button>

438

</div>

439

);

440

};

441

```