-
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
Runaway recursion when trying to access editor.value
in a plugin onChange
event
#2152
Comments
@ericedem what do you need to access |
We do a comparison of |
Basically just following this example: https://docs.slatejs.org/walkthroughs/saving-to-a-database Comparing |
Ok so, the JSFiddle I linked before doesn't actually reproduce the issue we are seeing in our dev environment. I'm having trouble reproducing in a fiddle or examples, but still working on it. While debugging, I noticed part of our infinite recursion is coming from this bit of code. When accessing Which creates a change on the value and forces all of the plugin change events to run again. |
Ok this will be reproducible with this fiddle once a new version of slate gets published with memoize-one@4.0.2. https://jsfiddle.net/uvkrn9ge/21/ The loop is:
The reason why this wasn't a problem before is that in 4.0.2, the behavior of memoize-one changed such that when you recurse in a memoized method, it doesn't remember what the result is until after the function finishes getting called, which will never happen because the recursion never terminates. So it just keeps seeing the same value and passing the same value check because it was never set. I think this is actually the correct behavior in What ends up making this even worse is that if you specify a schema in a plugin, the same schema check will also fail in I created a simple local slate example based on that fiddle and upgraded to |
editor.value
in a plugin onChange
eventeditor.value
in a plugin onChange
event
I see. The editor.value is unset during a stack run. @ianstormtaylor Shall we provides any compat for users to access editor.value during a stack? (when change.value is accessible). |
@ericedem For database thing, use componentDidUpdate or compare container.state.value with change.value. I would suggest use componentDidUpdate:
|
Thanks for the suggestion @zhujinxuan we can add the saving to the container if that's the official recommendation, though we are really trying to encapsulate pure slate behavior into plugins, since our containing component has already grown quite large. With all the components and custom plugins we have several thousand lines of code centered around managing the editor. I guess the main thing I'm still trying to grok, is why there are events or any kind of side effects being called in a getter, or even a memoized method. Looking at the code where this was added it looks like this code before ran on I realize that Sorry if these are naive musings, I'm a bit new to the codebase and missed the original PR when it was being written 😄 |
editor.props.value? It is doable in previous slate because we used state.value. However it is an anti-pattern as https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization |
Yep
Hmmm, I'm not sure this is an anti-pattern, though after rereading that document It seems like the editor would fall under the category of a "controlled" component, and props.value is the source of truth. This is a bit off the rails here, but bear with me:
Unfortunately I think this is a bit awkward to do in React now, because it needs to render something, and there isn't a great way to intercept prop changes. Maybe if we kept track of a |
@zhujinxuan That doesn't really fix the problem that this shouldn't be happening at all. I'm inferring from your PR that I should be using |
So I tried just using |
Hi @ianstormtaylor , @ericedem just reminds me that |
@ericedem I agree with you, the side effects on getters is very hard to understand, and leads to weird situations like this. I'm open to ways to fix this. The only constraint we currently have is that (as you said) rendering needs to always be with the "normalized" value based on the schema. Which creates a little conundrum for us. @zhujinxuan I'd like to omit the |
@ianstormtaylor How about the #2165? We allow user to access the editor.value during |
@zhujinxuan I'm not sure, it feels like it's going to add confusion still. I think the best solution would be to revert to the old way of handling things without the stateful getters if possible. |
One thing I have been thinking of is say we have two values This seems reasonable to me, the only trouble is when someone says |
@ericedem I don't think that handles the first render case, where we don't have a |
@ianstormtaylor Yea that's a good point, it would be null on first render. One thing we could do, is if we had a way to check if a value was "valid" without trying to do normalization, in |
Oh actually, it would probably be better to do this in the |
But there is a problem. We normalize the value by |
Hi, @ianstormtaylor @ericedem I make a PR for the PR: #2187 |
I don't think we need Though I think for performance reasons we could potentially make use of |
@ericedem The problem of setState with componentDidUpdate is the performance. Here is a issue about it #1938 Using |
Do you want to request a feature or report a bug?
Report a bug
What's the current behavior?
Get a depth exception when trying to access
editor.value
in a pluginonChange
event.Just try to load this fiddle and it will throw errors: https://jsfiddle.net/uvkrn9ge/1/
Chrome latest Mac OSX.
Note: I did narrow this down to a change in version 4.0.2 of
memoize-one
. I think this error may have always been happening, it was just covered up.The text was updated successfully, but these errors were encountered: