Skip to content

Commit

Permalink
Fix inactive handlers staying at finished state (#2738)
Browse files Browse the repository at this point in the history
## Description

While investigating #2370 I've found out that if handler has `enabled: false` and moves to state `END`, it won't reach `UNDETERMINED`. This fact makes it useless because it is stuck at finished state. It happens because of [this line](https://github.com/software-mansion/react-native-gesture-handler/blob/a30f42f3fe5f08e9746864a7e6f7a15d15936a0f/src/web/tools/GestureHandlerOrchestrator.ts#L118). In order to fix that, I've decided to reset handler in case if it moves to `END` state while being inactive.

Fixes #2730

## Test plan

<details>
<summary>Tested on the following code</summary>

```jsx
import React, { useState } from 'react';
import {
  View,
  SafeAreaView,
  Text,
  TextInput,
  TouchableOpacity as RNTouchable,
} from 'react-native';
import { TouchableOpacity as GHTouchable } from 'react-native-gesture-handler';

const BrokenGestureHandlerTouchable = () => {
  const [disabled, setDisabled] = useState(true);
  const [didClick, setDidClick] = useState(false);
  return (
    <View>
      <Text>
        Breaks with react-native-gesture-handler's TouchableOpacity. Refresh the
        page, click the disabled button, edit the text, click the button that
        should be enabled again and the click isn't triggered (no opacity change
        and no function call). If you refresh the page, edit the text, then
        click the enabled button, it works as expected.
      </Text>
      <TextInput
        placeholder="Text Input"
        placeholderTextColor="#AAAAAA"
        onChangeText={(text) => {
          setDisabled(false);
        }}
      />
      <GHTouchable
        disabled={disabled}
        onPress={() => {
          setDidClick(true);
        }}
        style={{
          borderWidth: 1,
          borderColor: 'pink',
        }}>
        <Text>Click me! {`Disabled: ${disabled}. Clicked: ${didClick}`}</Text>
      </GHTouchable>
    </View>
  );
};

const WorkingReactNativeTouchable = () => {
  const [disabled, setDisabled] = useState(true);
  const [didClick, setDidClick] = useState(false);
  return (
    <View>
      <Text>
        Works with react-native's TouchableOpacity. Refresh the page, click the
        disabled button, edit the text, click the now-enabled button again and
        it works.
      </Text>
      <TextInput
        placeholder="Text Input"
        placeholderTextColor="#AAAAAA"
        onChangeText={(text) => {
          setDisabled(false);
        }}
      />
      <RNTouchable
        disabled={disabled}
        onPress={() => {
          setDidClick(true);
        }}
        style={{
          borderWidth: 1,
          borderColor: 'pink',
        }}>
        <Text>Click me! {`Disabled: ${disabled}. Clicked: ${didClick}`}</Text>
      </RNTouchable>
    </View>
  );
};

export default function App() {
  return (
    <SafeAreaView>
      <WorkingReactNativeTouchable />
      <View
        style={{
          height: 50,
        }}
      />
      <BrokenGestureHandlerTouchable />
    </SafeAreaView>
  );
}

```

</details>
  • Loading branch information
m-bert authored Feb 5, 2024
1 parent a30f42f commit 3a23bfa
Showing 1 changed file with 4 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/web/handlers/GestureHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ export default abstract class GestureHandler {
);

this.onStateChange(newState, oldState);

if (!this.enabled && this.isFinished()) {
this.currentState = State.UNDETERMINED;
}
}

protected onStateChange(_newState: State, _oldState: State): void {}
Expand Down

0 comments on commit 3a23bfa

Please sign in to comment.