-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Manage Editable value as React element #466
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
blocks/components/editable/index.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we setContent( '' ) instead? What if it's an update?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we
setContent( '' )instead?
Oh, yes, I think I meant for this line to be content = '';
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in rebased d4f5a57c4854c11d405691b37824e63cefb3eab1.
blocks/library/text/index.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be something different than an array of undefined ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be something different than an array of undefined ?
Yes, I've added some clarifying comments and slightly adjusted the behavior to return early on an undefined content in the rebased d4f5a57c4854c11d405691b37824e63cefb3eab1.
Specifically:
// Content can be in the following shapes, so we normalize to an array:
// - Single paragraph: Object
// - Multiple paragraph: Array of objects
blocks/library/text/index.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When do we have a string here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When do we have a string here?
When splitting a paragraph into two, the default TinyMCE getContent was including a newline between the paragraphs which when parsed by html-to-react resulted in an [ Element, '\n', Element ]. In the rebased 075237ef5d3947a9f784c27580bf6ba9a9193a4e, I changed this to get content as raw formatted with the assumption that clean-up will occur as a result of html-to-react and renderToString (see also extended commit description).
blocks/components/editable/index.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be concerned about performance here? renderToString on each render and parse on each onChange ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be concerned about performance here?
renderToStringon each render andparseon eachonChange?
Yes 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not the intent of the change, but a trade-off that could help performance slightly is change to retrieve content from editor instance as raw formatted in 075237ef5d3947a9f784c27580bf6ba9a9193a4e.
e5d1d1d to
075237e
Compare
blocks/library/text/index.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we use castArray
youknowriad
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing that bothers me with this, is that Plugin authors would need to understand well React Elements.
The fact that it could be sometimes a single element and sometimes an array is a bit confusing I think. Shouldn't we always castArray in the parser and in the Editable?
Anyway, this solves the dangerouslySetInnerHTML issue and is worth a try
element/index.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I don't see much value in abstracting "React"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I don't see much value in abstracting "React"
What are you suggesting here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we just drop wp.element :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could probably be convinced. Needs to be a decision made with future compatibility in mind, related to some of the "reason to be" outlined in the docs:
https://github.com/WordPress/gutenberg/tree/master/element#element
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify my point, I don't see much value in abstracting React because we're using a lot of React features: Element, Component (refs, state, lifecycle), cloneElement, renderToString, render. Which is close to be the whole React.
Also, and this is probably the main reason for me. If we want to use a library like react-textarea-autosize or react-tooltip or any library dependent on React, we can do so (we're already doing it) technically and it'll work because we're using React but what if we switch our wp.element implementation to a custom React alternative, nothing guarantees that the libraries we're using are only using the React features we whitelist on our implementation. And this IMO should force us to avoid using any React third-party library because "logically" they're not dependent on our abstraction but they're dependent on React (which is a larger library).
I don't anticipate that they'd need to do any manipulation of the object, and I'm fine with it being slightly opaque in that regard. You're correct there would need to be some awareness of what the value is generally. The goal here is to eliminate plugin author consideration of markup strings. We could simply pass the So the question becomes: if we want to represent the caption, citation, or paragraphs nested elements as data, what shape does it take? I think there are some less complex options if we optimize for the value's shape to be inspected, but I don't think we care. A React tree seemed a natural fit into what we're already building. Aside: I'm not claiming you disagree with me on any of these points. Just trying to clarify (for myself and others) the rationale for this change. |
I'm not totally clear on the ramifications of this change, but I think it could make sense, sure. |
075237e to
0924fe6
Compare
|
Rebased again to resolve conflicts, and account for newly added Embed block. @youknowriad 0924fe6 is an improved approach to handling differing shapes of the parsed content, leveraging the fact that
https://facebook.github.io/react/docs/react-api.html#react.children And yes, I can totally appreciate that including this adds fuel to your argument that we should drop the abstraction 😆 Let's do that... but not here. |
0924fe6 to
f67320a
Compare
Default formatting is slower because it cleans the content. We don’t particularly care for this behavior since the React parser and subsequent renderToString will achieve the desired output
Designed for this purpose of handling opaque structure of children https://facebook.github.io/react/docs/react-api.html#react.children
f67320a to
82feb24
Compare
Closes #421
This pull request seeks to address issues with treating the Editable value as a string. Specifically, the need to manage a string value counteracts the promise of avoiding manual manipulation of HTML and adds complexity to serialization.
Related discussion at #413 (comment)
Implementation details:
childrenhpq matcher to extract content as a React element, using html-to-reactrenderToStringto handle more incoming value types (falsey, string, array)It's admittedly concerning to apply even more parsing in the form of HTML → React transformation, especially in juggling the incoming and outgoing value on the Editable (TinyMCE) component. I think we'll need to address this sooner than later, but the changes introduced here are aimed at shaping expectations of managing attributes of a block which contain elements.
Testing instructions:
Verify that there are no regressions of existing behavior:
Ensure included tests pass: