question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

mismatch between "editor" and "value" concepts

See original GitHub issue

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

Discussion.

What’s the current behavior?

Just opening this up for discussion, since it’s something that I think Slate hasn’t really solved well so far, and leads to it being hard to decide in either direction for the API…

Right now there are two concepts vying for the “top spot” in the architecture:

  1. value — which holds the document, the selection, the history and the schema. This can easily be created server-side (or wherever), since it’s not coupled to the view layer at all. (I’d consider change to be equivalent to value here, since they hold all the same data.)

  2. editor — which holds the plugins, the current value, and the schema to an extent. This is less easy to use server-side, since the editor is inherently tied to the view layer. (Although this need not always be the case.)

So far, it’s been unclear which is the “primary” concept. For example…

  • Event handlers are passed both a change and an editor to allow the user to decide which they want to use. You normally use the change, but sometimes, for example if you want to trigger an async change later, you need to use the editor.

  • For the idea of “commands and queries” from #2066, it’s unclear whether these commands should live inside the schema (or similar) and be exposed as change.command(...). Or whether, since they are tied to the plugins, they should be exposed as editor.command(...). Both have tradeoffs.

  • You could make the argument that history shouldn’t really be inside the value, and instead be controlled by the editor which is the long-lived entity—which would seem totally reasonable to me.

  • Right now there’s a confusion in that the editor’s plugins create a final schema object that gets set on the value. But the value can also be initialized with its own schema, which will be overwritten… and it’s not clear how they interact.

What’s the expected behavior?

I’m not totally sure. This is something that I’ve wrestled with, but never found a nice mental model for being clear about the distinctions between the two. I’d love for anyone with ideas to comment! (Even if you aren’t sure yourself, anything is helpful!)

I think it’s helpful to have a few goals:

  • It would be good for “commands”, “history”, etc. to all be able to be modeled in server-side environments where there is no concept of the “view” layer. This doesn’t necessarily mean it has to be the value model, but it has to be something that isn’t tied to the DOM or rendering.

  • It would be best if the top-level concept can unify the plugins, schema, history, commands, etc. in a way that makes it clear where all of this stuff stems from.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:18 (15 by maintainers)

github_iconTop GitHub Comments

3reactions
ericedemcommented, Sep 25, 2018

Hmm I’ve been wrestling with this one myself. The mental model I have for the Editor is that it is simply the view layer. Given a bunch of props like value / schema etc., Render something to the page. The value is then just the pure state of the app: what is the current snapshot of the app’s state.

I think the problem is that this gives us the “view” and the “model” but it doesn’t really tell us where the controller lives (in a traditional MVC architecture). So the current “controller” is a combination of change, value and the editor that don’t always know how to talk to each other. This is why there is some confusion about whether to make changes you need to talk to the value or the editor.

I wonder if there should be a third component like Controller that contains all the event / state management. Then the “editor” is just a simple view layer that renders and proxies interaction events into the controller. The controller would also just be pure non-react JS, easy to work with on the server side. It would probably also be easier to test than the editor.

The big downside I see to this is that in React a component is generally also the controller. This might cause us to move further away from React best practices.

2reactions
ianstormtaylorcommented, Oct 2, 2018

I’m just going to leave a summary of my current API architecture thoughts here…

  • Introduce the Editor controller. The piece is to introduce a new “plain JS” controller exposed in the core slate module, called Editor. It will contain the core editor logic (like ensuring normalization, running through the plugins stack, etc.) that is currently partly in slate-react. It will be used by slate-react, or on the server-side by itself, or in the future in non-React view layers to get the basic editor behaviors. If you exposed a Slate-like API to developers you could even bundle the Editor in your API library.

  • Fold the Stack into Editor. Once you have the concept of this editor controller, you don’t actually need the stack. It lives in “models” right now but it’s not really a model. It’s just thin layer around some iterations methods that can easily be moved to become methods on the Editor instance instead. This makes the public API more clear, such that plugins can invoke the stack if they have a need to (as the core plugin currently does).

  • Add a change.editor reference. Changes are actually editor-specific instead of value-specific like they are currently architected. This also clears up the idea that changes are “models”, while they are in a sense, they are not immutable like the rest of Slate’s models. By making them editor-aware we can…

  • Remove the schema property from Value. With the reference to change.editor and thus change.editor.schema, we no longer need to have the value.schema coupling which is confusing because the schema is really an editor-specific object. This also eliminates another “non-model” model, because the schema isn’t really a “model” in the sense of being serializable or immutable in the way that all other Slate models are. (This is a pattern, there are a handful of things in “models” right now that don’t really belong.)

  • Remove the value.change() method. Similarly, with changes now tied to the Editor controller, changes can no longer be created with only access to a value, because they rely on access to the editor’s schema to make decisions about how the change occurs (for example for void nodes).

  • Add the “commands” concept to the editor. This introduces a new concept called “commands” which are part of the Editor and can be defined in plugins. This relates to #2066 and allows for editor-level commands that can be defined in a single place, but used in many. It is very similar in approach to Redux Actions, or the Elm Architecture, in terms of having a pre-defined set of “commands” that can change the state. And now that the Change objects are editor-aware, each command can be exposed as change[command], exactly like the current change methods. Which brings us to…

  • Add “queries” support. I was originally thinking of these as two separate concepts, but I think instead commands could return values, in which case “queries” are just commands that return values but don’t add any operations to the stack. This way we don’t need to introduce an entirely new concept? Although it can be done either way, introducing a separate “queries” concept would work just as well.

  • Convert the current “changes” into commands. With the concept of commands introduced, all of what are currently called “changes” can now be implemented as commands in the core plugin, instead of the current custom approach. This is functionally equivalent, but it means that now even the core commands can be overridden for use cases that need it. (This is something that comes up somewhat often in Slack as a question, and isn’t easily solved right now by any other means.)

  • Convert History into commands on value.data. Right now the history is implemented as “changes” but it also special-cased in a way that makes it very hard to customized. With the new pluggable commands concept though, history can change to become three commands: save, undo, redo which are overridable by the user. And instead of needing to live in a custom History model, they can be implemented to live in the value.data namespace as data.undos and data.redos. This way users can implement their own history, using a totally different data structure if they’d like.


At the end you end up with a clearer delineations:

Layer Concepts
Model Value, Operations, Nodes, Marks, Ranges, Data
Controller Editor, Changes, Schema, Commands, Queries, History
View <Editor>, <Island>, render*

The only overlap remaining that I can see still is that “plugins” end up defining logic that lives in both the Controller and the View layers. But I’m not sure if there’s a way around this. (If anyone has ideas I’m open!)

How does that sound?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Solved: Type mismatch - Unable to convert a value to the d...
Getting datatype mismatch error when refreshing the report on Power BI Service. And I do not have permission to change datatype in the...
Read more >
VBA Type Mismatch Error - The Ultimate Guide
A VBA Type Mismatch Error occurs when you try to assign a value between two different variable types. The error appears as “run-time...
Read more >
C++ / Boost Filesystem - mismatch detected for '_MSC_VER ...
Opened that file in NP++ or text editor search for keyword _MSC_VER and changed the value /FAILIFMISMATCH:"_MSC_VER=1700" to ...
Read more >
Mismatch Definition - Investopedia
A mismatch refers to incorrectly matching assets and liabilities. It is commonly analyzed in situations pertaining to asset and liability management.
Read more >
A k-mismatch string matching for generalized edit distance ...
However, the execution time increases because of the bundle of complex computations for calculating complicated edit distances. The computational costs for ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found