Draft-js: Cannot fix SSR issue with editorKey prop

Created on 10 May 2017  路  10Comments  路  Source: facebook/draft-js

Do you want to request a feature or report a bug?
Report a bug.

What is the current behavior?
Causes bag with data-offset-key:

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) " data-offset-key="egvuv-0-0" data-react
 (server) " data-offset-key="enh8p-0-0" data-react

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. You can use this jsfiddle to get started: https://jsfiddle.net/stopachka/m6z0xn4r/.
Just draft-js with SSR. Cannot provide jsfiffle because of it doesn't have SSR (or has?).

What is the expected behavior?
SSR without reuse markup errors.

Which versions of Draft.js, and which browser / OS are affected by this issue? Did this work in previous versions of Draft.js?
0.10.1

Most helpful comment

@mxstbr I was able to reproduce the issue, and I think the reason is that the empty EditorState is being created fresh on the server, and then created fresh again on the client.

There is an example of SSR in our github repo, and it carefully uses the same data for the empty EditorState on both server on client -
https://github.com/facebook/draft-js/tree/master/examples/draft-0-10-0/universal

I think that if the block keys are different, Draft will think they are different content and re-render, even though you and I know they are both just a block with an empty string.

We could try to force Draft to avoid re-rendering and merge the block keys if their text and entity data is the same. I would rather not because it adds complexity, and because you have another solution: this seems solvable if you create a reusable emptyContentState like in the example.

Hope that is helpful!

All 10 comments

Hi @cassIn - are you passing in the 'data-offset-key' to Draft as a prop? This is how to fix the issue with SSR. Please see the example that demonstrates this. If you are already passing it in and still getting this error then please reopen and we can look into it.

Also thanks for using the latest version of Draft! :)

Hi @flarnie what's you mean by passing in the 'data-offset-key' to Draft as a prop? I don't see any data-offset-key props in the demonstrate example.

And as I followed the example, construct an emptyContentState, the data-offset-key error is disappear, but then every time i try to input or focus on editor, i got a new error:

image

Thanks for help:)

Hey @flarnie, I have an app that passes editorKey to all editors, yet I'm still getting the rehydration warning with the data-offset-key.

It only seems to happen with editors that have an empty initial state. I have two editors, one for the thread detail with lots of data and one for the chat input which is empty, and only the chat input one doesn't rehydrate correctly.

I verified this by logging in my custom <Editor /> component that I use everywhere:

class Editor extends Component {
  render() {
    console.log(this.props.editorKey);
    console.log(convertToRaw(this.props.editorState.getCurrentContent()));

    return <DraftEditor editorState={this.props.editorState} editorKey={this.props.editorKey} />
  }
}

This gives these logs on the server:

screen shot 2017-09-22 at 2 55 49 pm

and these logs on the client:

screen shot 2017-09-22 at 2 50 13 pm

Notice how the two editors have different editorKeys which are the same across server and client, but also notice how the React warning data-offset-key references the block key of the chat input editor with no content.

When I remove the empty editor (the chat input), no rehydration warning is logged. (in case that makes a difference, I generate that empty initial state with EditorState.createWithContent(ContentState.createFromText('')))

It'd be great to reopen this issue because I can't seem to find the reason behind this rehydration warning. I'm also using the draft-js-plugins editor in case that's relevant. /cc @juliankrispel

Thanks for all the details @mxstbr! Let's reopen this. I should have time to investigate more tomorrow.

Awesome, thank you @flarnie!

@mxstbr I was able to reproduce the issue, and I think the reason is that the empty EditorState is being created fresh on the server, and then created fresh again on the client.

There is an example of SSR in our github repo, and it carefully uses the same data for the empty EditorState on both server on client -
https://github.com/facebook/draft-js/tree/master/examples/draft-0-10-0/universal

I think that if the block keys are different, Draft will think they are different content and re-render, even though you and I know they are both just a block with an empty string.

We could try to force Draft to avoid re-rendering and merge the block keys if their text and entity data is the same. I would rather not because it adds complexity, and because you have another solution: this seems solvable if you create a reusable emptyContentState like in the example.

Hope that is helpful!

Ohh that makes total sense, sorry for the false alarm. Thank you so much for digging into this @flarnie, much much appreciated!

@flarnie hi could you help me though since i still got the same error too while following the link from the example, the problem appears when i try to use a decorator with createEmpty function

const decorator = new CompositeDecorator([
    {
        strategy: findLinkEntities,
        component: Link
    }
]);

this.state = {
    editorState: EditorState.createEmpty(decorator),
    title: '',
    urlValue: '',
    showURLInput: false
};

<Editor editorKey="foobaz" handleKeyCommand={this.handleKeyCommand}
        editorState={editorState} onChange={this.onChange}
        ref={(ip) => this.editor = ip} />
Was this page helpful?
0 / 5 - 0 ratings