4

I have a collection of multiple draft-js ContentStates which i want to merge together to display them in one <Editor />

Why? Through my GUI you can edit text snippets individually and then at a later point join them together. You are then presented with the resulting text, which you again can still edit.

I persist the individual ContentStates as follows:

const contentState = EditorState.getCurrentContent();
const raw = convertToRaw(contentState);

Which gives me an object like:

{
   blocks: [...],
   entityMap: {...}
}

What i tried, was manually merging the blocks and entityMap, to get a resulting raw contentState, which i could then parse with convertFromRaw

However, each block has a supposedly unique key, where on different contentStates these keys overlap and are not unique.

So the result in that case is that some blocks are being overridden by others with the same key.

Does anyone have an idea for an easier way to achieve what im doing?

Jan Benda
  • 152
  • 10

1 Answers1

0

There is a function in draft.js to generate unique keys:

import { genKey } from 'draft-js'

If you look at its code, you'll see that it's stateful (see that seenKeys?):

const seenKeys = {};
const MULTIPLIER = Math.pow(2, 24);
  
function generateRandomKey(): string {
    let key;
  
    while (key === undefined || seenKeys.hasOwnProperty(key) || !isNaN(+key)) 
    {
       key = Math.floor(Math.random() * MULTIPLIER).toString(32);
    }
  
    seenKeys[key] = true;
    return key;
}
  
module.exports = generateRandomKey;

So I believe, you can solve your problem by mapping over blocks and regenerating their keys (I'll use Ramda for more concise and expressive code):

import * as R from 'ramda'

const mergedObjectWithOverlappingKeys = {
   blocks: [...],
   entityMap: {...}
}

const result = R.evolve({
   blocks: R.map(R.assoc('key', genKey())),
})(mergedObjectWithOverlappingKeys)
dehumanizer
  • 1,250
  • 12
  • 15