Closed m-natarajan closed 2 days ago
Triggered auto assignment to @MitchExpensify (Bug
), see https://stackoverflow.com/c/expensify/questions/14418 for more details.
:wave: Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Triggered auto assignment to @techievivek (Engineering
), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.
@techievivek FYI I haven't added the External label as I wasn't 100% sure about this issue. Please take a look and add the label if you agree it's a bug and can be handled by external contributors.
This has the same root cause as https://github.com/Expensify/App/issues/33502#issuecomment-1907604187
Not a blocker for sure. Also, not sure if we really want to fix this. Or as per this comment https://github.com/Expensify/App/issues/33502#issuecomment-1909057724 we can solve all this together.
@MitchExpensify Do you have any thoughts about above ^?
Save button clicked by keyboard go back twice
When I tested, I found that there's no issue with react navigation or react native web. The issue is within our button component.
A simple check anyone can do, replace the button with the one from react-native, no issue :)
The issue is whith all the button components on the app. Every action via keyboard enter key will trigger double the action.
The condition above doesn't check if there's a keyboard enter key event.
The best way to handle here:
onPress={(event) => {
if (event?.type === 'click') {
const currentTarget = event?.currentTarget as HTMLElement;
currentTarget?.blur();
}
+ if (event?.type === 'keyup') {
+ return;
+ }
if (shouldEnableHapticFeedback) {
HapticFeedback.press();
}
return onPress(event);
}}
This will prevent the double actions on the Button component and will solve the related bugs.
Not worth fixing at this time
@MitchExpensify the issue is within all buttons on the app and there's an easy fix here
If there is a general solution its worth considering reopening, @techievivek does the solution linked above look like it will fix all cases of this?
@techievivek can you please check my proposal? Thank you
Adding a C+ so they can help review the proposal.
Job added to Upwork: https://www.upwork.com/jobs/~010769f678e16c288e
Triggered auto assignment to Contributor-plus team member for initial proposal review - @mkhutornyi (External
)
@mkhutornyi Can you please help review the proposal here https://github.com/Expensify/App/issues/37464#issuecomment-1971486442 and see if that can fix all the keyboard navigation related bugs? Thanks
@dragnoir thanks for the proposal.
We also should consider @bernhardoj `s comment here
@mkhutornyi The issue is old, it was there even before. Every button now on the app triggers action twice if you navigate to it via the TAB key then you hit the ENTER key from the keyboard. We can't catch it easily because triggering twice an action does not cause issues in most cases. But if you log the onClick with a console message, you will see it twice.
@nkdengineer on the comment you mentioned, bernhardoj think it's an issue from react native web and it needs to be fixed upstream. You can check here https://github.com/Expensify/App/issues/33502#issuecomment-1971614956 I fixed the issue there with the same proposal here.
@dragnoir Oh, got it. Thanks for your information
@techievivek @MitchExpensify @mkhutornyi this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!
@mkhutornyi What are our next steps here?
IOU - App returns to participant selection page when hitting Save with Tab on Description page
When we focus on the button component and then press on ENTER key, there are three events triggered: "keydown", "click", "keyup". It is the default behavior.
In the case of react-native-webs, generally, we handle two event, "click" and "keyup".
Here is logic to handle "click" and here is the logic to handle "keup"
When we focus on "Save" button and press ENTER, the "click" event listener is called first. Then, the "keyup" event listener is called. In the "keyup" event listener, we already have the logic to not call the onPress
function if the current target element is button
in here, but the elementType
in this case is body
(because we call Navigation.goBack
in the onPress
), so isNativeInteractiveElement
is false
. So the onPress
is called one more time.
This bug is not occur if the onPress
function does not contain the logic Navigation.goBack
We can fix this issue in our app instead of react-native-web library.
The idea is, to make sure in the case of the button, let click
event listener handles "ENTER" press action instead of keyup
.
To do it, in here, create a ref isHandledRef
to check whether the onPress action is handled.
const isHandledRef = useRef(false);
Then in here, early return if isHandledRef.current: true
:
if (isHandledRef.current) {
isHandledRef.current = false;
return;
}
Then add the additional logic to this:
if (event?.type === 'click' && event.detail === 0 && event?.target?.tagName === "BUTTON") {
isHandledRef.current = true;
}
in the above, event?.type === 'click' && event.detail === 0
to check if the 'click' event is triggered by ENTER action instead of a real 'click' action, event?.target?.tagName === "BUTTON"
to make sure this logic only applies to button component
Generally, we need to make sure the onPress function is only called one time.
First, create a flag in here, named isOnPressCalled
(default value is false
) to know whether the onPress
function is already called or not.
Then, add to here the below logic:
if(event.detail === 0){
this.isOnPressCalled = true
}
Finally, update this to:
if (onPress != null && !isNativeInteractiveElement && (!this.isOnPressCalled)) {
event.detail === 0
(event.detail
tell me how many click actions).elementType === 'button'
in here if (onPress != null && !isNativeInteractiveElement && elementType !== 'body') {
Gentle bump @mkhutornyi, can you please review the proposals today? Thanks.
I agree this is not upstream issue. We should either
I prefer 1. because it aligns with other Tab key press behavior (pressed on Down event, triggered on Up event)
I agree this is not upstream issue.
It's an upstream issue.
prevent our custom Enter key event when button is highlighted
There is no enter key shortcut triggered in this issue.
It's an upstream issue.
It's not. You can use the Button component from react native and the issue is not there anymore.
We don't handle events correctly. You can google the issue, this happened to lots of users having same framework as here and they solved it using this way
Oh you're right that it's not related to custom Enter key event which I initially thought.
I just tested passing disablePressOnEnter
to FormProvider
but bug still happening.
https://github.com/Expensify/App/assets/97676131/66b6dd14-0d51-46dd-add9-6087b40cb725
I think the expected behavior should be to trigger onPress on Up event like other views. Edit: But based on current structure of Button component, it seems not possible.
https://github.com/Expensify/App/assets/97676131/d996d51b-2b1d-4dc1-8a96-f515749a8fd2
and they solved it using https://github.com/Expensify/App/issues/37464#issuecomment-1971486442
I tested your solution and it throws a console error, that's why the second onPress
isn't triggered. Blurring the element on the second press event doesn't cancel the press event itself.
I think the expected behavior should be to trigger onPress on Up event like other views.
Most of the buttons on the apps use ROLE.BUTTON which renders it as <button>
. Native <button>
will trigger onclick
by pressing it down with the keyboard and react-native-web
calls onPress
from the onclick
event.
https://github.com/Expensify/App/assets/50919443/dd52aeaf-8958-44e9-958b-5882c7e550c9
The MenuItem role is menuitem
which will render it as a div
and react-native-web manually handles the click/press event in keyup
event and it makes sure the element is not a native interactive element (for example button).
https://github.com/necolas/react-native-web/blob/5f9c32eba0f840bde7b462a57d0748358ff866f6/packages/react-native-web/src/modules/usePressEvents/PressResponder.js#L305-L328
@bernhardoj looks like your upstream PR is stale. Created on Jan 24 but no one is taking care of it. Can you please bump reviewers?
@mkhutornyi Do you have any comment proposal](https://github.com/Expensify/App/issues/37464#issuecomment-2002357953) ?
@nkdengineer thanks for the proposal. Agree with RCA (though same as @bernhardoj's). Can you please try to fix in upstream?
@mkhutornyi if it's an upstream issue on,react-native-web why does changing the button from @components/Button with a button from react native solve the issue?
@dragnoir you meant Pressable
? @components/Button
is using Pressable
in low level.
@dragnoir you meant Pressable? @components/Button is using Pressable in low level.
@mkhutornyi yes right.
Can you please try this simple test? change this code here
add simple console function and assign it to the onSubmit
And add at the bottom a Pressable component with the same onPress={testPress}
+ const testPress = (event) => {
+ console.log('event: ', event);
+ console.log("Pressed");
+ };
<StepScreenWrapper
// rest of the code..
<FormProvider
style={[styles.flexGrow1, styles.ph5]}
formID={ONYXKEYS.FORMS.MONEY_REQUEST_DESCRIPTION_FORM}
+ onSubmit={testPress}
// ... rest on the code
+ <Pressable accessibilityRole="button" onPress={testPress}>
+ <Text>Press me</Text>
+ </Pressable>
</StepScreenWrapper>
This will show on the console how the Pressable
will trigger the action just once. But the Form (use the Bottom component) will trigger the action twice
⇒ This reflects that the issue is not upstream but in the way we handle press events.
if you want to read more about the issue you can check this link: https://stackabuse.com/bytes/triggering-button-click-with-javascript-on-enter-key-press/
The issue is mainly in this part of the code: https://github.com/Expensify/App/blob/156e9bfd9c86213ba3a2667dbdf5b505753dbdc8/src/components/Button/index.tsx#L286-L296
We are handling the click events separately causing the trigger of the key-up event. Also handling the event from a parent component causes something called Event Bubbling and Propagation described in detail on the link above
Those updates below fix the issue
onPress={(event) => {
event?.stopPropagation();
return onPress(event);
}}
or
onPress={(event) => {
event?.preventDefault();
return onPress(event);
}}
I have bumped the upstream PR. If the maintainer approves the PR (or if we want to create a patch), can we reopen https://github.com/Expensify/App/issues/33502 instead and include both issues in the App PR test step?
📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸
I have bumped the upstream PR. If the maintainer approves the PR (or if we want to create a patch), can we reopen #33502 instead and include both issues in the App PR test step?
Similar to https://github.com/Expensify/App/issues/38163#issuecomment-2000846846, I think we can fix here.
@mkhutornyi pls check my comment here https://github.com/Expensify/App/issues/37464#issuecomment-2004939788
@dragnoir if it's not upstream issue, what are the exact offending lines in the app?
@mkhutornyi pls check "SOLUTION" part here https://github.com/Expensify/App/issues/37464#issuecomment-2004939788
@dragnoir thanks. I confirmed that your RCA is correct. I see that you suggested 3 solutions. Which solution is the main one? And explain why it's the best solution over others.
I am no longer waiting upstream fix. And @bernhardoj's upstream fix was also rejected.
The root cause is indeed here but this is on purpose. onPress
should be called only once and while keep Enter pressed in, it should be not called anymore.
@mkhutornyi I like the solution I mentioned on my proposal
- if (event?.type === 'click') {
+ if (event?.type === 'click' || event?.type === 'keyup') {
const currentTarget = event?.currentTarget as HTMLElement;
currentTarget?.blur();
}
We keep everything as it is and we make sure we handle the keyup
event.
@dragnoir that solution didn't work. It causes console error and that's why the next lines were not triggered.
@dragnoir that solution didn't work. It causes console error and that's why the next lines were not triggered.
True, I forgot about it. I will check again.
📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸
@mkhutornyi Sorry for the delay, I wanted to test all possible solutions and check if there's an issue or regression.
This is the best way to handle here:
onPress={(event) => {
if (event?.type === 'click') {
const currentTarget = event?.currentTarget as HTMLElement;
currentTarget?.blur();
}
+ if (event?.type === 'keyup') {
+ return;
+ }
if (shouldEnableHapticFeedback) {
HapticFeedback.press();
}
return onPress(event);
}}
This will prevent the double actions on the Button component and will solve the related bugs.
I also agree with that approach. Please update proposal accordingly.
If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!
Version Number: 1.4.45-0 Reproducible in staging?: y Reproducible in production?: n If this was caught during regression testing, add the test name, ID and link from TestRail: Email or phone of affected tester (no customers): Logs: https://stackoverflow.com/c/expensify/questions/4856 Expensify/Expensify Issue URL: Issue reported by: Applause internal team Slack conversation:
Action Performed:
Expected Result:
The description will be saved and app will land on confirmation page.
Actual Result:
The description is saved and app returns to participant selection page.
Workaround:
unknown
Platforms:
Which of our officially supported platforms is this issue occurring on?
Screenshots/Videos
Add any screenshot/video evidence
https://github.com/Expensify/App/assets/38435837/0fb64f28-a879-431f-9c7c-73f8545689d9
View all open jobs on GitHub
Upwork Automation - Do Not Edit