Skip to content
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

Remove safeRenderCompletion and setImmediate hacks #1197

Closed
sbusch opened this issue Feb 26, 2019 · 5 comments · Fixed by #1720
Closed

Remove safeRenderCompletion and setImmediate hacks #1197

sbusch opened this issue Feb 26, 2019 · 5 comments · Fixed by #1720

Comments

@sbusch
Copy link
Contributor

sbusch commented Feb 26, 2019

This is a proposal for V2 project, where's the chance to get rid of setImmediate hacks regarding setState:

  • replace calls to custom setState wrapper (which uses setImmediate hack) with proper React setState calls and with callback where appropriate, and eliminate setState wrapper.
  • remove safeRenderCompletion
  • remove any other setImmediate hacks (at least outside of testing code)

The code to be removed makes assumptions about React behaviour and JS engine performance which don't work as they changed (and will change) over time.

See discussion at #891 (older: #562)

Related currently open issues: #1164, #1023 (maybe), #544, #513 (maybe), #446 I'm sure there are many other (potentially obscure) errors, mostly race-conditions, coming from this hack. See for example my PR #1068.

There's the possibility that bugs are raised or performance is degraded by that change, but these problems should always be fixable without a false setImmediate "fix".

P.S: nice to see that the project gains traction again, thanks for all working on it. We're happy to contribute!

@sbusch sbusch changed the title Remove safeRenderCompletion and setImmediate hacks Remove safeRenderCompletion and setImmediate hacks Feb 26, 2019
@sbusch sbusch changed the title Remove safeRenderCompletion and setImmediate hacks Remove safeRenderCompletion and setImmediate hacks Feb 26, 2019
@epicfaace
Copy link
Member

Thanks for making this issue. Do you know why exactly the custom setState wrapper with setImmediate was added in the first place? Will removing this necessarily be a backwards incompatible change that would require a v2?

https://github.com/mozilla-services/react-jsonschema-form/blob/f9d4c63cac24146e522528d33eb04f465464e052/src/utils.js#L786

@sbusch
Copy link
Contributor Author

sbusch commented Feb 26, 2019

No, I don't know why.

Some forensics:

  • the setState wrapper was introduced in 6159cb4, but this mostly refactored existing setImmediate hacks into this wrapper to enable central circumvention of setImmediate via safeRenderCompletion.
  • before that, many setImmediate calls (all of them?) were introduced in PR Improved async rendering strategy #153 "Improved async rendering strategy" by @n1k0

If I understand everything correctly:

  1. status quo: setState was used properly, with onChange within callback (so no problems with correctness, race conditions)
  2. it became clear that react-jsonschema-form is too slow: many components are stateless and there is no memoization. See Slow performance  #147. The examples linked there demonstrating the performance degradation are still working...
  3. first try to fix it was PR Attempt at providing memoization for stateless components. #152, using memoization (interestingly, the PR also introduces some setImmediate calls)
  4. it seems that during implementation of PR Attempt at providing memoization for stateless components. #152, using setImmediate showed so much promise that PR Attempt at providing memoization for stateless components. #152 was aborted in favor of PR Improved async rendering strategy #153

Regarding backwards compatibility:

In theory, after eliminating setState wrapper and setImmediate and after fixing the performance problems, everything should still just work™. But most definitely, some behavior will change slightly, people are relying on timings, and so on. So I would consider this a breaking change.

This is even more true if we take new React hooks into consideration, which could be a solution for the performance problem, since this requires upgrading the peer dependency on React to 16.8.0.

@hoppula
Copy link

hoppula commented Mar 1, 2019

After just spending three hours debugging why some keystrokes were skipped when typing rapidly in our complex form and then discovering the need for safeRenderCompletion={true}, big 👍 for removing these hacks.

@glasserc
Copy link
Contributor

glasserc commented Mar 6, 2019

Thanks for digging into this. I never really understood the purpose of those hacks myself. I'd love to see them gone.

sbusch added a commit to sbusch/react-jsonschema-form that referenced this issue May 17, 2019
by changing to proper use of setState() without setImmediate() hacks (see rjsf-team#1197)
@sbusch sbusch mentioned this issue May 17, 2019
5 tasks
epicfaace pushed a commit that referenced this issue May 22, 2019
* react-dom is external peerDependency, just like react.

fixes version conflicts, e.g. I got an error

  Uncaught TypeError: this.updater.enqueueCallback is not a function when using setState callback

because I use React 16.x and react-jsonschema-form bundled react-dom 15.x

See facebook/react#10320 (comment)

* Fix for new submit() method (PR #1058) also submitting the HTML form

..., navigating away from current page at least in Firefox. Reason:
dispatched event was not cancelable, so preventDefault in onSubmit
couldn't cancel it.

Links:

* <https://stackoverflow.com/a/40916998>
* <https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable>

* Synchronous call to onSubmit() from props

Due to the use of setImmediate() hack in setState utility function (utils.js),
onSubmit() handler from props is called asynchronously. This leads to massive
problems for operations requiring "trusted events", like window.open() or
programmatically submitting forms with target "_blank" (which we needed)

Because onSubmit() should not need the performance-related setImmiate() hack, I
replaced call to setState utility function with proper this.setState() from
React.

* fix failing FileWidget tests

by changing to proper use of setState() without setImmediate() hacks (see #1197)

* fix input type, fix test name

* Test with newer node versions

* Add node 12
@epicfaace epicfaace added this to To do in V2 via automation May 25, 2019
@mirajp mirajp mentioned this issue Sep 10, 2019
7 tasks
@epicfaace
Copy link
Member

This is nearly fixed by #1454, but we still have a few setImmediate hacks in the playground and tests that need to be removed: https://github.com/rjsf-team/react-jsonschema-form/search?q=setImmediate&unscoped_q=setImmediate

@epicfaace epicfaace moved this from To do to In progress in V2 Apr 25, 2020
V2 automation moved this from In progress to Done Apr 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
V2
  
Done
Development

Successfully merging a pull request may close this issue.

4 participants