akveo / react-native-ui-kitten

:boom: React Native UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/react-native-ui-kitten/
MIT License
10.33k stars 955 forks source link

onPress not firing until a few clicks on a Button #1392

Open edwardffs opened 3 years ago

edwardffs commented 3 years ago

💬 onPress not firing until a few clicks on a Button

Some buttons (I'll say "some" because I wasn't able the establish a pattern yet) I have to touch multiple times until the code in "onPress" method runs. Weirder yet, sometimes is instant.

At the moment, is happening on a button that calls a method to change a value in the component's state, in order to make a modal disappear (using the same method that openned it in the first place, without said issues).

What does happen always is the pressing animation. I'm fairly new to React-Native and UI-Kitten, so I may be doing something wrong. Is this behaviour a known "issue" that can be corrected?

Thanks in advance.

UI Kitten and Eva version

Package Version
@eva-design/eva ^2.0.0
@ui-kitten/components ^5.0.0
malashkevich commented 3 years ago

Hello @edwardffs, could you please add more details? It's not clear what platform, react-native version, device are you using. Also it would be nice to see the reproducing sample or at least the code you are using.

edwardffs commented 3 years ago

I'm on React-Native 0.63.4, Windows, and currently using my own phone for development (OP 6T). The code I'm using is as follows:

const FolderIcon = (props) => (
  <Icon {...props} name="folder" />
);

class SideDrawer extends PureComponent {

  static contextType = MainContext;

  constructor(props) {
    super(props);

    this.state = {
      findModal: false,
    };

  }

  loadConfigModal = (e) => {
    this.setState({
      findModal: !this.state.findModal,
    });
  };

  pickFile = () => {
    //TODO
  }

  render() {
    return (
      <>
        <CustomModal
          visible={this.state.findModal}
          content={
            <Card
              appearance={'filled'}
              status={'success'}
              header={() => (
                <Layout style={StyleSideDrawer.modal_header}>
                  <Text category={'h5'}>{translate('load_configuration')}</Text>
                </Layout>
              )}
              footer={() => (
                <Layout style={StyleSideDrawer.layout_modal_buttons} level={'2'}>
                  <Button style={StyleSideDrawer.button_modal} onPress={this.loadConfigModal}>
                    <Text category={'s2'}>{translate('cancel')}</Text>
                  </Button>
                  <Button status={'info'} style={StyleSideDrawer.button_modal} onPress={() => this.pickFile()}>
                    <Text category={'s2'}>{translate('app_location')}</Text>
                  </Button>
                  <Button status={'info'} style={StyleSideDrawer.button_modal} onPress={() => this.pickFile()}>
                    <Text category={'s2'}>{translate('custom_location')}</Text>
                  </Button>
                </Layout>
              )}
            >
              <Text category={'s1'}>{translate('load_configuration_message')}</Text>
            </Card>
          }
        />
        <MainContext.Consumer>
          {data => (
            data.appData !== null && data.appData !== undefined ? (
              <DrawerContentScrollView>
                <Layout style={{flex: 1, backgroundColor: 'rgba(0,0,0,0)'}}>
                  <Layout style={StyleSideDrawer.baseLayout}>
                    <Text category={'h6'} style={StyleSideDrawer.normalText}>{translate('upload_file')}</Text>
                    <Button accessoryLeft={FolderIcon} status={'basic'} style={StyleSideDrawer.modeButton} onPress={this.loadConfigModal}>
                      <Text style={StyleSideDrawer.buttonText}>{translate('find')}</Text>
                    </Button>
                  </Layout>
                </Layout>
              </DrawerContentScrollView>
            ) : (
              <></>
            )
          )}
        </MainContext.Consumer>
      </>
    );
  }
};

export default SideDrawer;

CustomModal is a wrapper using React Native's Modal, that receives a component to fill it (in this case, a UI-Kitten's Card).

The button that opens the modal (the one down below, with the 'upload_file' translation) works as expected. The issue happens using any of the buttons on the card in the modal.

I hope I was clear enough! Thank you for your time

EDIT: Buttons on Card's footers seem to be having this issue a lot 🤔

valinagacevschi commented 3 years ago

Might be related to this: https://github.com/facebook/react-native/issues/4087

stdavis commented 2 years ago

@edwardffs Did you ever solve your issue? I'm experiencing something similar with buttons in a card footer.

proffnick commented 2 years ago

If your component is inside ScrollView component, and you come across this behavior, add this keyboardShouldPersistTaps={true} to the ScrollView.

jaxoncreed commented 10 months ago

For anyone encountering this problem on web, I found that in cases where the user "hard presses" their cursor moves a bit between mouse-down and mouse-up. The way UI kitten set up its buttons, this will cause the web browser to think that the user wanted to highlight the text in the button, not press the button. The result is that it takes multiple presses of the button before the user gets lucky and does a click without moving the mouse.

My solution was turning off pointerEvents for the content inside the button. For example:

      <Button
        accessoryLeft={(props) => (
          <View pointerEvents="none">
            <Icon
              {...props}
              name="pause-circle-outline"
            />
          </View>
        )}
        onPress={pause}
      />
jeremyfrancis commented 1 month ago

Workaround is to just surround the Button or tappable component with from react-native-gesture-handler and this solves the issue right away.