This repository has been archived by the owner on Dec 15, 2022. It is now read-only.
Rewrite autobind calls as class properties #1850
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Please be sure to read the contributor's guide to the GitHub package before submitting any pull requests.
Requirements
Description of the Change
Rewrite bound functions throughout the package from using the
autobind()
helper function:To using class properties:
I've also made a small number of related changes:
autobind()
call have been removed.setState()
were modified to return aPromise
that resolves when the component's re-rendering is complete.Alternate Designs
The autobind helper was introduced in #1430 to replace the
@autobind
decorator. Decorator support was the only reason we had a dependency onbabel-eslint
, which was causing conflicts with a Relay upgrade.Rather than use class property syntax, we could:
Keep the autobind helper
The way we have it now is kind of a hack, but it does the job.
Downsides: non-standard and potentially surprising for contributors. It requires us to keep the list of method strings up-to-date with the methods defined on the class and fails hard if they drift. It also makes it non-obvious which methods are bound and which are not at the method declaration sites.
Re-introduce decorator support
We'd need to find a way to do this without breaking babel, istanbul, and Relay.
Downsides: I couldn't figure this out the last time that it came up, so I'm hesitant to give it another shot, especially because (as I understand it) the future of decorators in JavaScript proper is uncertain.
Hand-bind functions when used
We could use
.bind()
to bind methods when they're used in a context that requires them to be bound:Downsides: it's pretty inefficient; this will create a new Function object on every render, which will be referentially unequal, which can in turn prevent
OtherComponent
from being optimized to skip unnecessary renders by detecting when its props are unchanged. Furthermore, if more than one callsite needs a bound function, different Functions will be created for each of those. Also, it isn't obvious at the method declaration site whether the method is bound or not.Using an arrow function directly in
render()
has similar drawbacks.Hand-bind functions within constructors
We could use
.bind()
to manually bind functions within class constructors:Downsides: it's very verbose, it requires constructors on many components that otherwise wouldn't need them, and it makes it non-obvious which method are bound and which are not at the method declaration site.
Benefits
The biggest immediate benefit will be consistency. We'll have a single pattern for bound methods throughout our codebase, which should reduce surprise as we move around, etc.
This pattern should also be less surprising to contributors, as (unscientifically) React developers are moving toward class properties:
Possible Drawbacks
It's possible that I could accidentally introduce a regression here. Our tests should catch it though 🤞
Applicable Issues
I could swear I saw @kuychaco file one about this but I cannot for the life of me find it now.
Metrics
n/a
Tests
n/a
Documentation
n/a
Release Notes
n/a
User Experience Research (Optional)
n/a