Real-world examples of force renders in DraftJS โ a.k.a. When/How to use EditorState#forceSelection

EditorState
has a static method called forceSelection
. It should be used when you want to re-render the editor โ with selection and focus โ forcefully.
Here is what is said about it in the docs:
๐ forceSelection
static forceSelection(
editorState: EditorState,
selectionState: SelectionState
): EditorState
Returns a new EditorState
object with the specified SelectionState
applied, forcing the selection to be rendered.
This is useful when the selection should be manually rendered in the correct location to maintain control of the rendered output.
โ๏ธ A couple of real-world instances of forceSelection
usage
1) To fix the focus on undo when the editor state is being set from an external widget
When you set the state from an external widget outside the editor (for instance the +
button that appears in empty blocks, in the editor at hashnode.com), the state just before the editor state is set doesn't have focus; and when you do an undo, it causes a faulty selection.
You would do something like the following to handle this case
...
keyBindingFn = keyEvent => {
const isCommandPlusZ = KeyBindingUtil.hasCommandModifier(
keyEvent
);
if (isCommandPlusZ) {
const selectionBeforeHasFocus = editorState
.getCurrentContent()
.getSelectionBefore()
.getHasFocus();
if (!selectionBeforeHasFocus) {
return 'focus-editor-after-undo';
}
}
return getDefaultKeyBinding(keyEvent);
}
handleKeyCommand = (command) => {
if (command === 'focus-editor-after-undo') {
const newEditorState = EditorState.undo(
this.state.editorState
);
this.onChange(
EditorState.forceSelection(
newEditorState,
newEditorState.getSelection()
)
);
return 'handled';
}
return NOT_HANDLED;
};
...
render() {
<Editor
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.keyBindingFn}
...
/>
}
...
2) In **draft-js**
v0.9, **entities**
are decoupled from **contentState**
; so the change from updating an entity, doesn't reflect immediately in the editor...
Note: This behaviour is fixed, thanks to new Entity API in draft-js v0.10. Check this migration guide.
If you're working with 0.9 or below, you would have to forcefully render the selection again, a means to re-render the editor, whenever you update an existing entity.
Here's an example, whenever the user uploads an image from the image uploader present inside the +
button in the editor at hashnode.com; the image is blurred until it is uploaded to the corresponding CDN; and once that is done, the corresponding entity data is updated. Following is an excerpt from the codebase
uploadUserImage(src)
.then(res => {
let url = res.image;
// Preload image, before updating the entity with the new source
fetch(url)
.then(() => {
Entity.mergeData(
imageEntityKey,
{ src: url, uploaded: true }
);
// The following forceSelection needs to be done because
// the entity data is decoupled from the contentState,
// and a change in it doesn't trigger a re-render of the editor
this.onChange(
EditorState.forceSelection(
this.state.editorState,
this.state.editorState.getSelection()
)
);
})
});
๐ฆ Conclusion
As you have seen, you can use forceSelection
whenever you want to control the render, selection, and focus in the editor.
Have you gone through any examples where you needed a force render in a DraftJS editor? Let me know! ๐
Subscribe to my newsletter
Read articles from Sai Kishore Komanduri directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sai Kishore Komanduri
Sai Kishore Komanduri
I have been in love with computers and everything related since I played my first game of Dangerous Dave back in the 90s. Graduating with a master's degree in Biology, and a bachelor's in Pharmacy; I have been fortunate enough to dabble my hands in things ranging from copywriting to computer networks. I love pixel art! I've written a few more things about me, here and here!