Slate: Value to React view

Created on 4 Jul 2018  Â·  8Comments  Â·  Source: ianstormtaylor/slate

Do you want to request a _feature_ or report a _bug_?

Feature

What's the current behavior?

If you want to display rich text edited by Slate in React, you have to use the html serializer, and then put it as the html content of some div. If you want to use a custom component, you can't do this.

It would be great if there was a stripped-down "react serializer component" that takes a value (result of .toJSON()) and some rules and then can be used as a regular component.

It would be even greater if it would not need Immutable to do this.

What's the expected behavior?

<SlateValue value={value} rules={rules} /> puts the edited text where it's mounted, using the components defined in the rules.

If there is already something like this somewhere, it would be great if that could be made into a package for slate.

idea

Most helpful comment

We made slateToReact.js which converts from slate JSON representation to a React tree.

  • This is mostly the serialize logic from slate-html-serializer, except that it works on the JSON and not the Immutable object.

    • In particular, it doesn't call getLeaves but just uses the leaves array

  • I wonder if maybe this code can be factored out somehow? I'd love to see this be part of the Slate packages
  • Will the JSON representation change in the future?

    • In particular, it seems to be rather wordy and it keeps all the empty objects and arrays.

    • It would be nice if the JSON could be made more compact and get a version field so that parsers know if/how they are supposed to parse this.

    • I also wonder if the JSON structure could be memoized, since it gets built on every keystroke.

All 8 comments

We made slateToReact.js which converts from slate JSON representation to a React tree.

  • This is mostly the serialize logic from slate-html-serializer, except that it works on the JSON and not the Immutable object.

    • In particular, it doesn't call getLeaves but just uses the leaves array

  • I wonder if maybe this code can be factored out somehow? I'd love to see this be part of the Slate packages
  • Will the JSON representation change in the future?

    • In particular, it seems to be rather wordy and it keeps all the empty objects and arrays.

    • It would be nice if the JSON could be made more compact and get a version field so that parsers know if/how they are supposed to parse this.

    • I also wonder if the JSON structure could be memoized, since it gets built on every keystroke.

This is very cool! So in my understanding, calling this function on serialized Slate Value would return React component free, similar to what <Editor readOnly /> does? Because in that case I can save a lot of downloading and parsing time for my users... Been meaning to do this for a while.

Yes correct, you store the JSON object, use this function and put it somewhere with appropriate CSS.

We have an auto-sizing Image component that now works, and I'm thinking about maybe some component that interpolates values from a given context object, so we can do i18n with placeholders defined in Slate…

Awesome, will try tonight. Have you considered making it into a repo & npm package?

Can I know what it differs from <Editor editable={false}/>?

@dmitrizzle I'm not quite at the level for making a package yet, plus I'd prefer it if this functionality was part of Slate somehow

@zhujinxuan the difference is that it doesn't need to load Slate nor Immutable, which saves quite a bit of resources. Plus, it uses serialization rules to render, not the renderX functions, so it can render completely different things.

Thinking some more about this, it would be great if plugins would provide renderViewX (for each type), and then that would be used by a generic renderView that takes a Slate JSON value and returns the children.

Note that those view functions would be working on plain values.

However, the difficult bit is getting that renderView without pulling in the rest of the plugins and their dependencies (Immutable etc). It would have to be a separate file in a plugin package. Likewise, slate-react could export a View component from a separate file.

To make it simpler to use that View, perhaps the serialization could be provided by a Provider. So in your app you'd do

import View from 'slate-react/View'
import pluginAView from 'slate-plugin-a/view'
import pluginBView from 'slate-plugin-b/view'

const plugins = [ pluginAView(), pluginBView() ]

const App = ({slateJsonValue}) => (
  <SlateProvider plugins={plugins}>
    <View value={slateJsonValue} />
  </SlateProvider>
)

So 'plugin/view' exports a plugin with minimal dependencies and only the renderView function, and 'plugin' exports the whole thing as usual.
The View component would also be available on the regular 'slate-react'.

I believe that this may be fixed by https://github.com/ianstormtaylor/slate/pull/3093, which has changed a lot of the logic in Slate and slate-react especially. I'm going to close this out, but as always, feel free to open a new issue if it persists for you. Thanks for understanding.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

markolofsen picture markolofsen  Â·  3Comments

ezakto picture ezakto  Â·  3Comments

ianstormtaylor picture ianstormtaylor  Â·  3Comments

chrpeter picture chrpeter  Â·  3Comments

ianstormtaylor picture ianstormtaylor  Â·  3Comments