-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Only use Slate Provider's value prop as initial state #4540
Conversation
🦋 Changeset detectedLatest commit: 754bed9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
d70a644
to
aee4e40
Compare
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.
This needs a changeset, and it needs review by a few others as I don't have the history of experience to know with certainty if this change is ok (it seems ok).
Not sure whether to use a |
This is a breaking change. It should be a major bump. |
The documentation needs to be updated as well. |
onChange should not be the only way of changing the Component's value. If you rely on a database to render your content, you'll also want to pass the new value using the value prop. In that case you don't want to rely on a local state that is changed with onChange. An example would be when you need to display someone else changes to the value. |
Pre 1.0 beta so not a major bump.
How do you reconcile that with the discussion at #3575 (comment) ? |
I am ok with either way. But the documentation over here https://docs.slatejs.org/walkthroughs/06-saving-to-a-database should be updated. |
Besides the docs, the examples should probably also be updated to reflect this change which means just passing |
It is not the right way for an api, you shouldn't changed it. better to have the same signature as the native input api |
First of all, I want to say thanks to @ianstormtaylor and @bryanph for maintaining and continuing to build a great library. Regarding these changes, I wonder whether they actually fix the issue mentioned in #3575: const Editor = () => {
const [value, setValue] = useState('')
return (
<input value={value} onChange={(e) => setValue(e.target.value)} />
)
} Consequently, these changes entailed that to be able to interact with the value outside of const Editor = () => {
const editor = useMemo(() => withReact(createEditor())), [])
const [value, setValue] = useState('')
return (
<Slate
editor={editor}
value={value}
onChange={setValue}
>
...
</Slate>
)
} to this: const Editor = () => {
const editor = useMemo(() => withReact(createEditor())), [])
const [value, setValue] = useState('')
editor.children = value
return (
<Slate
editor={editor}
value={value}
onChange={setValue}
>
...
</Slate>
)
} Note the need to manually set the value of On a separate note, I think changes to the API should be added to the changelog as "Breaking Changes" instead of "Minor Changes" specially if a previous behaviour is no longer supported. I personally find it helpful to use standardised versioning system like Semantic Versioning and Keep a Changelog. Thanks! |
In general I agree, though we have not yet reached a 1.0 release. I would say at this point every minor update has likely broken someone somewhere. I'm not 100% certain what will lead us to decide that we're at 1.0, but I still see a lot of core things to improve and make more flexible before I would consider Slate stable. |
@KarimNahas The problem is that whenever
I find people generally get confused by the "passing value" API as it seems to indicate that's how you propagate changes, the "reacty" way. But in reality slate operates on Also see these two comments: #3575 (comment) and #3575 (comment) That said I do understand the desire to reset the editor to some particular value. Perhaps we could provide a convenience method for this? Something like |
@bryanph I definitely see how, since Consequently it think exposing / creating a method that enables the user to safely mutate the editor children would definitely be nice. What about adding a method called export const NodeTransforms: NodeTransforms = {
...
/**
* resetNodes resets the value of the editor.
* It should be noted that passing the `at` parameter may cause a "Cannot resolve a DOM point from Slate point" error.
*/
resetNodes<T extends Node>(
editor: Editor,
options: {
nodes?: Node | Node[],
at?: Location
} = {}
): void {
const children = [...editor.children]
for (let i = 0; i < children.length; i++) {
const node = children[i]
editor.apply({ type: 'remove_node', path: [0], node })
}
if (options.nodes) {
const nodes = Node.isNode(options.nodes) ? [options.nodes] : options.nodes
for (let i = 0; i < nodes.length; i++) {
editor.apply({ type: 'insert_node', path: [i], node: nodes[i] })
}
}
const point = options.at && Point.isPoint(options.at)
? options.at
: Editor.end(editor, [])
if (point) Transforms.select(editor, point)
}
...
} Also, I believe that renaming What are your thoughts ? |
@dylans TL;DR I think that I understand that My recommendation is to try and define what does stable mean for for Also, I don't think that a library should reach its full maturity / potential before getting bumped to a Lastly, on a personal note, I've been working on a project for about 2 years now. I used to be quite protective of the version number and stayed on |
I also think the documentation could need some update regarding how to update the editors value. I had a rather common use-case: async loading contents from my backend. Therefore couldnt set it as init value in Docs left the impression to me that you can use |
@philicious agreed about the docs, although for async loading you can simply defer rendering the editor until the content is fetched. |
* Refs #142010 - Optimize Volto-addons gitflow pipelines * Revert to older version of slate-react without the breaking API change * Upgrade slate and slate-react versions which brings up the problem with the breaking API change in Slate-React: ianstormtaylor/slate#4540 * Split text block editor components in separate modules * [JENKINS] Fix eslint * Make it work with new react-slate method of getting the value * Multiple Description blocks on the same page update each other In fact, does the changes to the SlateEditor component for the Slate-based Title & Description blocks too. * Remove useless commented line * Backwards block merge 2 (#195) * Solve bug when merging blocks with Backspace * Remove some dead code * Update Jest snapshots * Update Jest snapshots Co-authored-by: Silviu Bogan <silviubogan@gmail.com> * Automated release 5.1.2 Co-authored-by: valentinab25 <valentinab25> Co-authored-by: Silviu Bogan <silviubogan@gmail.com> Co-authored-by: Alin Voinea <contact@avoinea.com> Co-authored-by: EEA Jenkins <@users.noreply.github.com>
* Refs #142010 - Optimize Volto-addons gitflow pipelines * Revert to older version of slate-react without the breaking API change * Upgrade slate and slate-react versions which brings up the problem with the breaking API change in Slate-React: ianstormtaylor/slate#4540 * Split text block editor components in separate modules * [JENKINS] Fix eslint * Make it work with new react-slate method of getting the value * Multiple Description blocks on the same page update each other In fact, does the changes to the SlateEditor component for the Slate-based Title & Description blocks too. * Remove useless commented line * Backwards block merge 2 (#195) * Solve bug when merging blocks with Backspace * Remove some dead code * Update Jest snapshots * Update Jest snapshots Co-authored-by: Silviu Bogan <silviubogan@gmail.com> * Automated release 5.1.2 * [JENKINS] Refs #142010 - Optimize Volto-addons gitflow pipelines * Automated release 5.1.3 Co-authored-by: valentinab25 <valentinab25> Co-authored-by: Silviu Bogan <silviubogan@gmail.com> Co-authored-by: Tiberiu Ichim <tiberiu.ichim@gmail.com> Co-authored-by: Alin Voinea <contact@avoinea.com> Co-authored-by: Tiberiu Ichim <tiberiuichim@users.noreply.github.com> Co-authored-by: EEA Jenkins <@users.noreply.github.com>
Slate value only sets initial value. ianstormtaylor/slate#4540
Works for the first load of the editor, but what if you want to return to the original state of the editor after changing the values? For example:
How do you tackle this problem? Is it still with EDIT: I'm failing to see this at the documentation even months after. Am I missing something? |
@bsides I would (try to) save the original content in state, then use |
Since the original content is external, that's saving props as state, which is an anti pattern. I'm updating to |
@bsides ye in case you consider the content being updated from other places, you need to fetch it again and not use state. or use state + employ mutex locking in your content DB to only allow single edit instance |
The thing is, this is a pretty trivial thing for a form to do: to be trully controllable in case we have external data being pulled/pushed asynchronously. Right now it's really not a good implementation because it's trying to do 2 things and failing in both. |
Would like to +1 on the need to making this clearer in the documentation. For me anyway this is a very common use-case and directly setting |
Is there a chance that this can be reverted? I think it was never justified in the first place, but seeing the problems it created just confirms this. |
I am having issues with this solution now that I updated to 0.9 due to trying to fix another bug. This solution causes a lot of side effects on 0.9 even when it used to work previously. For example when I use Transform.setNodes now it won't update because it will trigger render with the old value, however with keypresses it will register, and only sometimes. I think now editor.children have to be manually set every time, so while this solution may work some of the time it will not work all of the time, not anymore. |
Just dropping a note for anyone using slate-history… (slate@0.94.1, slate-history@0.94.0) Setting const editor = useMemo(() => withHistory(withReact(createEditor())), []); I see in @KarimNahas example #4540 (comment) that we can instead use I ran into an additional problem getting the cursor focus to remain on undo though. I tried adding |
Hey there Slate community, just want to share my recent attempt at implementing this feature. Where changing the value prop updates the content shown on the editor. const resetEditor = <T extends Node = Node>(editor: Editor, nodes?: T | T[]) => {
const { selection } = editor;
editor.removeNodes({ at: { anchor: editor.start([]), focus: editor.end([]) }});
if(nodes) editor.insertNodes(Node.isNode(nodes) ? [nodes] : nodes);
editor.select(selection ?? editor.end([]));
}; Rough example of how you could use it: const Editor = ({ value, ...props }) => {
const editor = useMemo(() => createEditor(), []);
useEffect(() => {
// Extra logic...
resetEditor(editor, value); // Where the magic happens!
}, [value]);
// Rest of the editor code. Where Hope this helps ✌️! |
@SantosOMartinez , this is a nice idea, but unfortunately it doesn't work in my case. My problem:
Using the way Santos suggested will result in so many renderings for same content. Really hope this can be solved. What I'm doing now is a parameter (props:{useEffect?:boolean}) set useEffect and direct editor.children(need to make sure the useEffect:true will be no external change on the content) - kind of ugly... |
Description
As is made clear by the following issue #3575, the
value
prop that must be passed to theSlate
provider is kind of a hoax because in reality this prop has to be exactly what has been passed toonChange
. This changes theSlate
provider to relax this requirement. Thevalue
prop is now only used on the initial render to initialize thevalue
prop. On subsequent changes it is ignored.This also clears the way to rename
value
toinitialValue
as the prop is really intended to be.I'm curious whether this misses some subtlety in the rendering code that I'm unaware of. Please do educate me if so 😄
Issue
Fixes: #3575
Checks
yarn test
.yarn lint
. (Fix errors withyarn fix
.)yarn start
.)yarn changeset add
.)