Slate: "Warning: Prop `data-offset-key` did not match" (React, Next, webpack-hmr)

Created on 7 Jan 2018  路  6Comments  路  Source: ianstormtaylor/slate

I've just upgraded from Slate version 0.19.20 to 0.32.0. All the new changes seem like improvements (bravo!). But, there's a new behavior that's completely blocking my development. I've spent hours to trying solutions but am out of ideas. I'd love your suggestions / solutions.

I use React and the Next.js framework, which uses webpack-hmr ("Hot Module Replacement") to auto-update the browser when server-side or client-side dev code changes. This is invaluable for development.

I tried Slate's Checklist example with React 16.2 and Next 4.2.1. The first time the example renders when the server starts, the Slate example works fine. When I refresh the browser, or when code changes which auto-updates the browser, there's an error in the browser console (presumably from React):

Warning: Prop data-offset-key did not match. Server: "6:0" Client: "3:0"

Each time I refresh without doing anything else, the Server version in the warning goes up by 3:

Warning: Prop data-offset-key did not match. Server: "9:0" Client: "3:0"
Warning: Prop data-offset-key did not match. Server: "12:0" Client: "3:0"
etc.

After that first refresh, Slate breaks. The Value.selection doesn't change despite moving the cursor. Typed characters appear at the beginning of the text even though the cursor is elsewhere. I have to manually restart the server to get it working again. This makes development so painful I'd rather switch to a different editor library rather than make development this painful. Slate is a core part of what we're building. I also worry that this behavior might fail in production, but I haven't tried it.

Is there anything in the way data-offset-key is used in the code that could cause this problem? I looked at the Slate code where data-offset-key is mentioned, but I didn't get anywhere.

Any ideas?

It's some work, but if it will help, and if you'll engage with this issue, I'll create a dummy project with this problem for you to run.

gif: http://recordit.co/06btFHGuwj
OS is macOS 10.13.2
Browser is Chrome Version 63.0.3239.84 (Official Build) (64-bit)

question

Most helpful comment

Future readers: I had a problem very similar, if not identical, to the above and solved it by calling resetKeyGenerator() before the first Value.fromJSON({...}) call I made.

Note: Your first call to Value.fromJSON({...}) may perhaps be outside any of your classes/components as it is in a few of the walkthroughs in the docs, e.g. 'Installing Slate'.

All 6 comments

Hey @tashburn, the data-offset-key is calculated using the keys for the nodes themselves. Are you using the resetKeyGenerator method on the server-side rendering code path? I think that might be required to have the keys match up?

@ianstormtaylor, thanks for the prompt response and solution. I was already using resetKeyGenerator with the old version of Slate, but I was running it once when the server started. I forgot about it, and it was working fine.

Now, when I run resetKeyGenerator in the constructor of my outermost react component, that eliminates the problem. Thank you.

@tashburn: similar problem here, on the same version of nextjs. when you say outermost component, do you mean _document.js, or the page/component that wraps <Editor />?

@majelbstoat Each of my pages has a Page superclass. I put resetKeyGenerator() in the constructor of Page. Works so far.

I tried putting resetKeyGenerator() in _document.js, but it didn't work in the constructor() or in getInitialProps().

Did you find a different solution?

No, that's great. I was having difficulty with multiple editors on the page. calling resetKeyGenerator() inside each was not working - led to some weird shared references, but reseting in the constructor of the calling context worked well. Thanks!

Future readers: I had a problem very similar, if not identical, to the above and solved it by calling resetKeyGenerator() before the first Value.fromJSON({...}) call I made.

Note: Your first call to Value.fromJSON({...}) may perhaps be outside any of your classes/components as it is in a few of the walkthroughs in the docs, e.g. 'Installing Slate'.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ianstormtaylor picture ianstormtaylor  路  3Comments

ianstormtaylor picture ianstormtaylor  路  3Comments

yalu picture yalu  路  3Comments

markolofsen picture markolofsen  路  3Comments

chrpeter picture chrpeter  路  3Comments