react-native-web icon indicating copy to clipboard operation
react-native-web copied to clipboard

Pressable triggers onPress twice, when activated via Enter key and set to disabled

Open efoken opened this issue 1 year ago • 1 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Describe the issue

When using the onPress prop on the Pressable component and setting it to disabled inside the onPress-function, the function will be called a second time. But only when activating the button via the Enter key.

First time onPress is called when pressing the Enter key down and the second time it is called when releasing the Enter key. I created a test case which demonstrates this behaviour.

Expected behavior

onPress is only called once, like it is when using Space key oder pressing the button with the mouse.

Steps to reproduce

  1. Use <Pressable role="button"> and apply an onPress handler to it
  2. Set a disabled state inside the onPress handler
  3. Set the disabled prop using the state on your Pressable
  4. Put some console.log inside the onPress handler
  5. Activate your button using the keyboard, pressing the Enter key
  6. See your console.log twice in the console

Test case

https://codesandbox.io/s/react-native-web-on-press-disabled-77crwk

Additional comments

No response

efoken avatar Nov 09 '23 11:11 efoken

Is there a workaround for this till the fix is provided?

seemX17 avatar Feb 12 '24 16:02 seemX17

This is causing multiple form submissions in our application, resulting in duplicate database lines. Not ideal!

Because we never legitimately want to quickly submit a form twice in a row, I'm adding a throttle wrapper around the submit handler on our submit button

// This is a temporary fix until https://github.com/necolas/react-native-web/issues/2605 is fixed
// Prevent calling the submit function twice in quick succession (within 0.5 seconds). The first
// call completes immediately - it just blocks any subsequent calls within 0.5 seconds.
const throttle = <Callback extends (...args: any[]) => any>(callback: Callback) => {
  let disabled = false;

  return (...args: Parameters<Callback>): ReturnType<Callback> | undefined => {
    if (disabled) {
      return;
    }

    disabled = true;
    setTimeout(() => {
      disabled = false;
    }, 500);

    return callback(...args);
  };
};

jkjustjoshing avatar Mar 07 '24 21:03 jkjustjoshing

@necolas any idea when you're planning on a new release that includes this fix?

jkjustjoshing avatar May 29 '24 21:05 jkjustjoshing

It's been out for a week already 54c14d64dabd175e8055e1dc92e9196c821f9b7d

necolas avatar May 30 '24 10:05 necolas