Skip to content

Commit

Permalink
feat: update React docs
Browse files Browse the repository at this point in the history
  • Loading branch information
nperez0111 committed Nov 21, 2024
1 parent 45403ac commit 08f3183
Showing 1 changed file with 48 additions and 18 deletions.
66 changes: 48 additions & 18 deletions src/content/guides/performance.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,38 +77,39 @@ export default App

These unrelated components will cause the editor to re-render more often than necessary, and make each render more expensive.

### Gain more control over rendering
### Track down performance issues

As of Tiptap v2.5.0, you can gain more control over rendering by using the `immediatelyRender` and `shouldRerenderOnTransaction` options. This can be useful if you want to prevent the editor from rendering immediately or on every transaction.
You can use the React DevTools Profiler to see which components are re-rendering and why. Another strategy is to put a `console.count('editor render')` in the editor component and see how often it is re-rendered. This can help you identify which components are causing unnecessary re-renders.

If it is re-rendered more often than you expect, you can take the following steps:

- Check if the editor is rendering because of its parent component.
- Isolate the editor from unrelated state changes (e.g. opening a sidebar should not cause the editor to re-render).
- Use `useEditorState` to prevent unnecessary re-renders within the editor component.

Hopefully, these tips will help you track down and fix any performance issues you encounter.

### Use `useEditorState` to prevent unnecessary re-renders

The `useEditorState` hook allows you to subscribe to changes in the editor state and re-render only when necessary. This can help you prevent unnecessary re-renders of the editor and its components.

```tsx
import { useEditor } from '@tiptap/react'
import deepEqual from 'deep-equal'
import { useEditor, useEditorState } from '@tiptap/react'

function Component() {
const editor = useEditor({
extensions,
content,
/**
* This option gives us the control to enable the default behavior of rendering the editor immediately.
*/
immediatelyRender: true,
/**
* This option gives us the control to disable the default behavior of re-rendering the editor on every transaction.
*/
shouldRerenderOnTransaction: false,
})

const editorState = useEditorState({
editor,
// This function will be called every time the editor state changes
selector: (editorInstance: Editor) => ({
selector: ({ editor }: { editor: Editor }) => ({
// It will only re-render if the bold or italic state changes
isBold: editorInstance.isActive('bold'),
isItalic: editorInstance.isActive('italic'),
}),
// This function will be used to compare the previous and the next state
equalityFn: deepEqual,
})

return (
Expand All @@ -131,8 +132,37 @@ function Component() {
}
```

## React NodeView Integration
The `selector` function allows you to specify which parts of the editor state you want to subscribe to. By default this will be deeply compared with the previous selected state, and only re-render if it has changed. You can select any part of the editor state, or even derive new values from it.

### Gain more control over rendering

As of Tiptap v2.5.0, you can gain more control over rendering by using the `immediatelyRender` and `shouldRerenderOnTransaction` options. This can be useful if you want to prevent the editor from rendering immediately or on every transaction.

```tsx
import { useEditor } from '@tiptap/react'

function Component() {
const editor = useEditor({
extensions,
content,
/**
* This option gives us the control to enable the default behavior of rendering the editor immediately.
*/
immediatelyRender: true,
/**
* This option gives us the control to disable the default behavior of re-rendering the editor on every transaction.
*/
shouldRerenderOnTransaction: false,
})

return <EditorContent editor={editor} />
}
```

## React node views performance

Node views allow you to render custom components in place of nodes within the editor. This enables you to embed any kind of content in your editor. However, when using React components, be aware of potential performance implications.

While NodeViews with React are supported, if you are using them in your editor, you should be aware that they can be expensive to render.
For technical reasons, node views are expected to be rendered synchronously. Tiptap will create new elements for each node view and mount your React component in them. This can be expensive, especially if you have many instances of node views throughout your editor.

If you want the absolute best performance, your NodeViews ideally would not be rendered by React. Instead you could use direct DOM manipulation to render them. This is because React is not optimized for rendering synchronously and NodeViews are expected to be rendered synchronously. This is especially important if you have several instances of NodeViews throughout your editor.
We've optimized as much as possible on our side, but if you find that rendering node views is causing performance issues, consider using plain HTML elements or a different approach to render your content within your node view.

0 comments on commit 08f3183

Please sign in to comment.