Hello, thanks for the great work you are doing here. I have a minor issue, due to get-window (https://github.com/webmodules/get-window) library using in several places in the core (plugins, models, etc.), slate doesn't work in the server-side, get-window using browser only variables like window and document, I understand is using to detect if the window is an iframe.
Best regards.
I also really need server-side rendering to work (with next.js)
@Antherkiv can you paste an example or a stacktrace of the error you're getting, so people tackling this issue have a starting point? It's not immediately clear how this would break, since window methods tend to be used in response to user interaction.
If you need a quick workarond. You can import your slate editor with dynamic imports.
This allows you to render the Editor Component on client only.
```js
import React from 'react'
import dynamic from 'next/dynamic'
const DynamicLoadedEditor = dynamic(
import('./MyAwesomeSlateEditor'),
{
loading: () => (
loading...
),export default DynamicLoadedEditor
````
@HaNdTriX Thanks for the idea.
Just to clarify. I am using slate with next.js and it works like a charm.
The markup is rendered on the server without my workaround above.
Thanks for the great work @ianstormtaylor!
@HaNdTriX Did you have to do anything special to get it to render server side w/ Next.js? I keep getting an error: Unable to find a DOM node for "3". This is often because of forgetting to addprops.attributesto a custom component.
@rkrueger11 yes you need to reset the key generating function.
I just created a next.js example for this.
https://github.com/zeit/next.js/pull/4899
import React from 'react'
import Plain from 'slate-plain-serializer'
import { Editor } from 'slate-react'
import { KeyUtils } from 'slate'
class Index extends React.Component {
constructor (props) {
super(props)
// In order to allow ssr we need to reset the key
// generating function to its initial state.
KeyUtils.resetGenerator()
// Deserialize the initial editor value.
this.state = {
value: Plain.deserialize(
'This is editable plain text, just like a <textarea>!'
)
}
}
render () {
return (
<Editor
placeholder='Enter some plain text...'
value={this.state.value}
onChange={this.onChange}
/>
)
}
onChange = ({ value }) => {
this.setState({ value })
}
}
export default Index
@ianstormtaylor I think this issue can be closed.
Thanks @HaNdTriX!
There is now an offical next.js example: https://github.com/zeit/next.js/tree/canary/examples/with-slate
@HaNdTriX It works but when you clear the inputbox and type something on the field again it gives the error: Unable to find a DOM node for "2". This is often because of forgetting to addprops.attributes to a custom component.
I've got multiple instances of slate on a page, and @HaNdTriX's fix won't work for me.
Whenever I try and focus one of the slate instances, it will always focus the first one. https://codesandbox.io/s/zkzx818ryx. I presume this is because the keys are being reused across instances.
I'm not sure of a fix that will work with SSR and multiple instances. The global nature of KeyUtils isn't ideal.
Any ideas?
If you need a quick workarond. You can import your slate editor with dynamic imports.
This allows you to render the Editor Component on client only.import React from 'react' import dynamic from 'next/dynamic' const DynamicLoadedEditor = dynamic( import('./MyAwesomeSlateEditor'), { loading: () => (<p>loading...</p>), ssr: false } ) export default DynamicLoadedEditor
thank, this's really works
@tuanhuu
thank, this's really works
Yeah I'll have to do this for now I think, but it's not really a fix.
@ianstormtaylor should I raise another issue for this?
Just tried the quick fix disabling SSR for the editor component in React, it works! But still waiting for a proper fix that works with SSR @ianstormtaylor
The KeyUtils.resetGenerator() works for slate instances that rendered with SSR, but crash for slate instances that are later generated on the client side (got max callstack error once I focus on the slate editor)
Here is how I quick fix it for now:
import React from "react"
let SlateEditor
class Editor extends React.Component {
componentDidMount() {
SlateEditor = require("./SlateEditor").default
}
render() {
if (SlateEditor) {
return (
<SlateEditor
{...this.props}
/>
)
}
return null
}
}
export default Editor
@HaNdTriX any tips on getting this to work with multiple slate instances?
@juhaelee the issue is that data-key are starting from 0 for each instance of the Editor due to KeyUtils.resetGenerator(). So when clicking on an Editor, it focuses to the first data-key of the dom, thus being the first Editor instance and the second one becomes unfocusable.
Slate provides a KeyUtils.setGenerator(myKeygenFunction) to pass our own key generator. This gives us the opportunity to create truly unique keys across Editor instances.
In the parent that imports this component, pass a different idFromParentIteration prop for each instance of PlainText component and you should be good. Like so:
['first-editor', 'second-editor'].map((name, idx) => <PlainText idFromParentIteration={name + idx} />)
And here's a complete example with a custom key generator.
import React from "react";
import Plain from "slate-plain-serializer";
import { KeyUtils } from 'slate';
import { Editor } from "slate-react";
const initialValue = Plain.deserialize(
"This is editable plain text, just like a <textarea>!"
);
class PlainText extends React.Component {
constructor(props) {
super(props);
let key = 0;
const keygen = () => {
key += 1;
return props.idFromParentIteration + key; // custom keys
};
KeyUtils.setGenerator(keygen);
}
render() {
return (
<Editor
placeholder="Enter some plain text..."
defaultValue={initialValue}
/>
);
}
}
export default PlainText;
@rklhui I'm facing the same issue and have to disable SSR to have the editor not crash in editing mode. Did you figure out a different solution?
What is the solution in Slate 0.50+ now that KeyUtils has been removed?
Most helpful comment
@rkrueger11 yes you need to reset the key generating function.
I just created a next.js example for this.
Next.js-Example
https://github.com/zeit/next.js/pull/4899
SSR-Example
@ianstormtaylor I think this issue can be closed.