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

Fix NPE for mouse/touch handlers in StrictMode #657

Merged
merged 1 commit into from
Nov 25, 2022

Conversation

pradeepnschrodinger
Copy link
Collaborator

Description

When React's StrictMode is turned on, certain methods like lifecycle methods, constructors, setState methods, etc will be double invoked (in dev mode).
In fact, in future versions, it's possible that the same instance might be mounted/"destroyed" multiple times.

In StrictMode, the order of constructor/Lifecycle methods being called changes to:

constructor
componentDidMount
componentWillUnmount
componentDidMount

However, our code in FDT is written under the assumption that life cycle methods are just called once.
So the current code only initializes the mouse/touch handlers in the constructor, and destroys them in componentWillUnmount.
This leads to the second call to componentDidMount working with invalid mouse/touch handlers, thus causing a NPE.

Fix

The fix was to move out initialization and cleanup to separate methods, namely _setupHandlers and _cleanupHandlers.
Setting up the handlers will be done in both the constructor and componentDidMount methods.
Cleaning up will be done in just the componentWillUnmount method.

I've also added guard checks to ensure we won't reinitialize/cleanup more than needed.

Motivation

Avoid errors in future versions of React/StrictMode.
Fixes #656.

How Has This Been Tested?

Tested in local examples as well as the repo linked in #656 (https://github.com/savaparoski/not-working)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.

Tie up with setting up and cleaning up listeners to lifecycle methods under the assumption that
lifecycle methods like `componentDidMount`/`componentWillUnmount` might be called multiple times
for the same instance.
@pradeepnschrodinger
Copy link
Collaborator Author

@Tanner-MS , do you recall if the issue in #615 was in production?
I'm trying to figure out if the issue there came due to StrictMode.

}

_setupHandlers() {
if (!this._wheelHandler) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added guard checks to ensure we won't create handlers more than once.

This lets us call _setupHandlers multiple times.

this._divRef &&
this._divRef.removeEventListener('wheel', this._wheelHandler.onWheel, {
if (this._divRef) {
this._divRef.addEventListener('wheel', this._wheelHandler.onWheel, {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need a guard check here cause the event handler is a static function reference, so multiple addEventListener calls don't add duplicate entries.

@@ -1037,6 +1060,8 @@ class FixedDataTable extends React.Component {
this._divRef = div;
if (this.props.stopReactWheelPropagation) {
this._wheelHandler.setRoot(div);
} else {
this._wheelHandler.setRoot(null);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picked this up along the way.
Not exactly sure how we'll hit this code, but logically this just resets the root node if the prop is also reset.

@Tanner-MS
Copy link
Contributor

@Tanner-MS , do you recall if the issue in #615 was in production? I'm trying to figure out if the issue there came due to StrictMode.

Yes this was with production code.

@pradeepnschrodinger
Copy link
Collaborator Author

Yes this was with production code.

Ah, then it's unlikely that it was the same issue mentioned here. Thanks for the confirmation.

I also see that the lifecycle methods of the components touched in #615 setup/cleanup the handlers properly, so it shouldn't be an issue, even for later versions of React.

@pradeepnschrodinger pradeepnschrodinger merged commit f9e36cb into v1.2.x Nov 25, 2022
@pradeepnschrodinger
Copy link
Collaborator Author

Released with v1.2.12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants