Draft JS FIND entity in editorState

Gaurav Sobti
3 min readJun 20, 2020

Hi guys, here I provide a function to find an entity inside draft js editorState. To make it easy for you guys, I straightaway provide you the final solution, as many of us are on a tight schedule and don’t have time to go through the explanation. After that, if you are interested in understanding the solution, you can jump to the part 2.

Search Icon made by Freepik from www.flaticon.com

Part 1: Solution

To avoid making this post too long, I am providing the link to the gist. This solution is also available at the end.

Part 2: Explanation

Let’s start by looking at our function signature:

export const getEntitiesByLogic = ({ editorState, findEntity }) => {};

We pass editorState and a findEntity function. We are using a function here to be able to pass a custom logic and keep our main function modular. This is how findEntity function looks like:

const findEntity = ({ type, data }) => {
return type === 'mention' && data.id === 1;
}

Now back to our main find function, editorstate(content) contains data as an array of blocks. This is how the content inside editorState looks as a JSON:

// this state contains a mention entity whose text is my name: Gaurav Sobti
{
blocks: [
{
key: '23ich',
text: 'hello @Gaurav Sobti I am using draftJS',
type: 'unstyled',
depth: 0,
inlineStyleRanges: [],
entityRanges: [
{
offset: 6,
length: 13,
key: 0
}
],
data: {}
}
],
entityMap: {
'0': {
type: 'mention',
mutability: 'IMMUTABLE',
data: {
id: 'g3rfds324',
name: 'Gaurav Sobti',
title: 'JS Developer'
}
}
}
};

If you are curious how to get the above json from editorState:
convertToRaw(editorState.getCurrentContent());

1. We need to get all entities inside our text.

For that we will use block array and inside that block we will find entity.

const content = editorState.getCurrentContent();
const entities = [];
content.getBlocksAsArray().forEach(block => {
let selectedEntity = null;
block.findEntityRanges(
character => {
// here we will use our findEntity logic
// we will find entity by character and then store its data
},
// where does this entity start from and end in text
(start, end) => {
// here we will push the entity to our result
}
);
});
return entities;

We don’t need to explicitly know about findEntityRanges function. Just that it accepts two functions as parameters.
If you need to you can find more about findEntityRanges function here.

2. We need to use our logic function and find the entity that we are looking for

block.findEntityRanges(
character => {
if (character.getEntity() !== null) {
const entityKey = character.getEntity();
const entity = content.getEntity(entityKey);
const entityData = entity.getData();
const entityType = entity.getType();
// If our logic is successful
if (
findEntity({ type: entityType, data: entityData })
) {
// set data
selectedEntity = {
entityKey,
blockKey: block.getKey(),
entity: content.getEntity(character.getEntity())
};
return true;
}
}

return false;
},
(start, end) => {
entities.push({ ...selectedEntity, start, end });
}
);

Finally our function looks like this:

We use the above function like this:
const entities = findEntitiesByLogic({editorState, findEntity});

Result that we get:

const results = [{  
entityKey: "myEntityKey",
blockKey: "myBlockKey",
entity: EntityObject,
start: 4,
// start position of the entity
end: 10
// end position of the entity inside text
}]

I hope the explanation above didn’t get too confusing. Please let me know in the comments section down below if there is something else that needs to be explained.

--

--