-
-
Notifications
You must be signed in to change notification settings - Fork 1k
[Web] Fix handling of enabled
prop
#3726
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
base: next
Are you sure you want to change the base?
Conversation
packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts
Show resolved
Hide resolved
packages/react-native-gesture-handler/src/web/tools/GestureHandlerWebDelegate.ts
Show resolved
Hide resolved
packages/react-native-gesture-handler/src/web/tools/EventManager.ts
Outdated
Show resolved
Hide resolved
packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts
Show resolved
Hide resolved
} | ||
|
||
public setGestureConfig(config: Config) { | ||
this.resetConfig(); |
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.
If I understand correctly, the issue is that we reset the config here, but if the gesture was disabled before, we don't reattach the event listeners. Shouldn't we also try to attach listeners when resetting the config? At first glance, it looks like it could simplify this a lot (especially if it were to be done in a setter).
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.
Shouldn't we also try to attach listeners when resetting the config?
But in that case if we have config
that has enabled
set to false
we will first attach and then immediately detach listeners. Is that something that we want?
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.
Can we reverse that and start with detached listeners which are then attached when config has enabled !== false
?
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.
So instead of attaching listeners in resetConfig
, we should detach them, and then attach if enabled !== false
?
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.
If I understand correctly, the issue is that we reset the config here, but if the gesture was disabled before, we don't reattach the event listeners.
Also, I don't know whether we will have any other logic that depends on enabled
change, but I think that we should say that what the issue really is is that in current setup it is impossible to detect that enabled
has changed to true
*. This may (or may not) cause other troubles in the future.
* If we go through resetConfig
first, with SharedValue
it should be fine.
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.
If I understand correctly, you want to react only to config.enabled
, without comparing it to previous value is that true? If so, what in situation where two subsequent updateGestureConfig
will have enabled: true
? I guess we could check if listeners are already attached and do nothing in that case, but I think it solves only part of the problem.
Right now, onEnabledChange
in GestureHandlerWebDelegate
does some other things, i.e.:
this.setUserSelect();
this.setTouchAction();
this.setContextMenu();
So even if we solve problem with listeners, we still have issues where those functions won't be called because we can't detect when enabled
value changes to true
.
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.
If I understand correctly, you want to react only to config.enabled, without comparing it to previous value is that true?
No - IIRC, currently, we start every gesture with enabled: true
and listeners attached. We could start every gesture with enabled: false
and listeners detached. Then compare config.enabled ?? true
with the previous value and attach/detach if needed.
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.
But wouldn't it make it the same problem, but with false
instead of true
? If we make false
default value, and then in updateGestureConfig
we receive config.enabled = false
, we won't trigger onEnabledChanged
, even if user changed it from true
.
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.
I'm not sure I see it. Could you do a step-by-step on what needs to happen to get that?
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.
We could start every gesture with enabled: false and listeners detached.
I assume this means that when we reset handler, we set this.enabled
into false
. Let's say that we have this example:
const [enabled, setEnabled] = useState(true);
const pan = Gesture.Pan().enabled(enabled)
The flow here is:
- Reset
this.enabled
tofalse
(via callingsetGestureConfig
) - Compare
config.enabled
withthis.enabled
At first this works fine, we compare config.enabled
which is true
with this.enabled
which is false
. But now, when we change enabled
to false
, we have the same comparison, but both values are false
, so onEnabledChange
will not be called as we did not detect change from true
to false
- we lost that information in resetConfig
.
Description
Right now, if one changes
enabled
property of handlers tofalse
, they can never activate again. In the following example:gesture will never become active, even if
enabled
changes totrue
. Same happens whenenabled
is set totrue
and then changed tofalse
andtrue
again.This happens because we set
enabled
totrue
by default insetGestureConfig
, thus the following check:passes only when
config.enabled
isfalse
.To fix this, I've set
enabled
tonull
by default, and then ifconfig.enabled
is defined, it is assigned given value. Else default will betrue
.Alternative approach would be to follow Android implementation and always react to changes in$\rightarrow$ $\rightarrow$
enabled
even in cases likefalse
false
andtrue
true
.Test plan
Tested on the following code: