Skip to content
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

Add additional events for controlling picker indicator on web #15673

Merged
merged 6 commits into from
Mar 15, 2023

Conversation

redstar504
Copy link
Contributor

@redstar504 redstar504 commented Mar 6, 2023

Details

I had to work through this a bit more to make the picker indicator behave consistently all platforms. As proposed, I added two new event handlers specific to the web version of the app that update the isOpen state, but they needed to be adapted a bit from what I suggested.

The original proposal worked to solve the reported issue, but it was causing the picker to remain highlighted on desktop web after selecting an item. To solve this, I switched from using onClick to onMouseDown. This solved it simply because of the order the event handlers are called in.

In addition, I included a new onChange event handler whose presence overrides the onValueChange handler for web. This was necessary because my original solution of setting isOpen to false in the onValueChange event was resulting in the indicator changing back to the default setting whenever a new item was scrolled to in the iOS picker wheel.

Fixed Issues

$ #15506
PROPOSAL: #15506 (comment)

Tests

  1. Login to the app and navigate to any page containing a Picker component.
  2. In this issue, we used the Settings > Workspace > Reimburse Expenses picker for selecting mileage units.
  3. Open the picker and confirm that the green indicator beneath the picker is bright green while the picker is open.
  4. Select an item. Confirm that after selecting an item the indicator returns to it's default dark green color.
  • Verify that no errors appear in the JS console

Offline tests

QA Steps

  1. Login to the staging environment and navigate to any page containing a Picker component.
  2. In this issue, we used the Settings > Workspace > Reimburse Expenses picker for selecting mileage units.
  3. Open the picker and confirm that the green indicator beneath the picker is bright green while the picker is open.
  4. Select an item. Confirm that after selecting an item the indicator returns to it's default dark green color.
  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android / native
    • Android / Chrome
    • iOS / native
    • iOS / Safari
    • MacOS / Chrome / Safari
    • MacOS / Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I verified the translation was requested/reviewed in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

Screenshots/Videos

Web

Safari

border-mac-safari.mp4

Chrome

Having an issue with OBS not displaying <select> elements during a windowed screen recording (seems like select elements are considered a separate window), but still demonstrates the functionality:

pf-desktop-web.mp4
Mobile Web - Chrome
pf-android-chrome.mp4
Mobile Web - Safari
border-ios-safari.mp4
Desktop
pf-mac-desktop.mp4
iOS
pf-ios-native.mp4
Android
pf-android-native.mp4

@redstar504 redstar504 requested a review from a team as a code owner March 6, 2023 01:00
@melvin-bot melvin-bot bot requested review from marcaaron and thesahindia and removed request for a team March 6, 2023 01:00
@MelvinBot
Copy link

@marcaaron @thesahindia One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@MelvinBot
Copy link

Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers!

@thesahindia
Copy link
Member

@redstar504, the picker stays highlighted when we close it without changing the value

Screen.Recording.2023-03-06.at.11.36.13.PM.mov

I think we should handle this case as well.

cc: @marcaaron for thoughts

const index = e.target.selectedIndex;
const value = e.target.options[index].value;
this.onInputChange(value, index);
this.setState({isOpen: false});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like we are sneaking in some platform dependent code here, but it's not clear which is the web or native implementation. Normally, how we deal with that is create a "base" component and then an index.js and index.native.js components. In a file like Picker.js we'd then just import the Picker but the platform dependent changes would be contained in the respective versions of the picker. Would this approach work here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that would be better. Also let's create a function in index.js file and call it in onChange (just to make this a little bit cleaner)

@marcaaron
Copy link
Contributor

@thesahindia I don't feel super strongly about solving that case in this ticket. We didn't spot it until now and it's not clear what the solution would be - so I say we continue here and then file it as a separate bug. Unless @redstar504 has some idea on how to tackle it and is willing to look into it.

@thesahindia
Copy link
Member

That makes sense to me!

@redstar504
Copy link
Contributor Author

@marcaaron @thesahindia Thanks for the input guys. I have been exploring ways to split up the platform-specific code as requested. It appears that our goal is to share the Picker component across all platforms while providing a means to specify any platform-specific event handlers through their respective index files.

Would it make sense to refactor Picker.js into Picker/BasePicker.js, containing all of the platform independent handlers, and then import BasePicker into the platform specific index files? We could pass any platform specific event handlers to BasePicker as props to enable customization for each platform.

@thesahindia
Copy link
Member

Would it make sense to refactor Picker.js into Picker/BasePicker.js

Yes!

@redstar504
Copy link
Contributor Author

My latest commit includes platform specific event handling for the Picker component. The implementation involves wrapping the refactored BasePicker with platform specific entrypoint files, and wrapping the entrypoints with a higher order component that supplies default events for both platforms. Web specific events are encapsulated in the index.js file. Native events are supplied as defaults through the HOC since they supplement the web-based events.

Testing on all platforms was successful, and I have included new recordings in my checklist.

@marcaaron @thesahindia

import {pickerPropTypes, pickerDefaultProps} from './Picker/pickerPropTypes';

export default function (WrappedComponent) {
class WithSharedEvents extends Component {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't delved deeply into the reasons for needing it, but is an HOC necessary? Feels like the "WrappedComponent" is always going to be the Picker.

Additionally, I'm having trouble following some of the conventions used here e.g. the callbackConsumer() (stuck out to me as unusual for our codebase and my instincts are telling me it could confuse people).

I'd have to do a deeper dive to come up with more concrete suggestions, but just wanted to toss that observation out there that maybe we could simplify this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HOC wraps the Picker in both entrypoints (index.js and index.native.js), so that we can share all of the code contained in it between them. This also gives us a way to manipulate the events passed down to BasePicker using an entrypoint file. I originally had placed the HOC in the Picker directory because it would only ever be used for the Picker, but I noticed all of the others were contained in the base src directory so I moved it there.

An HOC would seem like overkill but I am kind of stuck between a dead simple solution (the one I originally provided), and an over-engineered solution. I have been having trouble finding something in the middle ground that won't introduce a lot of code duplication. Another option might be class inheritance.

We basically need a way to share all of the event handlers between both entrypoints but give the web entry point a way to extend/override them before passing them down to BasePicker. If you have any alternative ideas for that please let me know. If we stick with the HOC I can definitely rename callbackConsumer back to onInputChange.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An HOC would seem like overkill but I am kind of stuck between a dead simple solution (the one I originally provided), and an over-engineered solution. I have been having trouble finding something in the middle ground that won't introduce a lot of code duplication. Another option might be class inheritance.

Yeah I agree the original solution was simple, this feels a little over-engineered now. I am going to defer to @marcaaron on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see the issue now - sorry for the distraction here. I think where this is at is a bit hard to reason about for not much gain.

Here's what I'm thinking as an alternative...

  1. Start by reverting what you have here back to 15fb9c7
  2. Create some prop like shouldUseAdditionalPickerEvents on the Picker
  3. Override the methods that way inside the Picker

It might seem vain, but we can get around the cross platform file extension convention this way and it will allow web/native to switch on/off the functionality we need without specifically referencing the platform anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcaaron Thank you for the advice. I just need a bit more clarification:

It might seem vain, but we can get around the cross platform file extension convention this way and it will allow web/native to switch on/off the functionality we need without specifically referencing the platform anywhere.

Are you suggesting not having platform-specific entry points in this case? I am just curious what is going to toggle shouldUseAdditionalPickerEvents if we don't, and if we didn't, where do we define the web-specific events?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant something like...

/Picker/index.js -> <Picker shouldUseAdditionalPickerEvents />
/Picker/index.native.js -> <Picker />

Copy link
Contributor Author

@redstar504 redstar504 Mar 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcaaron Ok I will give that a shot. Since it's just a conditional in the entry points, is this implying that we keep the web events defined in the Picker itself? Just want to clarify exactly what we're after to avoid further delays.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

implying that we keep the web events defined in the Picker itself

That was my meaning yea.

But I thought of something that is slightly better and might result in fewer changes while avoiding a reference to the web specific e.target...

  • Create getAdditionalPickerEvents()
    • have native return {}
    • have web return something like
// getAdditionalPickerEvents/index.js
function getAdditionalPickerEvents(onMouseDown, onChange) {
    return {
        onMouseDown,
        onChange: (e) = {
            if (e.target.selectedIndex === undefined) {
                return;
            }
            const index = e.target.selectedIndex;
            const value = e.target.options[index].value;
            onChange(value, index);
        },
    };
}

Then pass them like:

pickerProps={{
    ...getAdditionalPickerEvents(this.setIsOpen, this.updateAndClose),

This feels slightly better to me as it manages the web event outside of the cross platform Picker code. Sorry for all the back and forth. Our style guide sometimes paints us into a corner 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcaaron I like the looks of that. I have been trying to find a way to pass down the events from the web entry, but also to be able to pass a function back that can enable/disable the highlight without having to reference them from inside the shared Picker. This looks like it could work.

Also, no worries. I am happy to work towards something we can all be satisfied with.

@redstar504 redstar504 force-pushed the Brayden-PickerIndicator branch from 40c36bc to 6e3b8fc Compare March 10, 2023 04:26
@redstar504
Copy link
Contributor Author

That concept worked perfectly @marcaaron, nice job.

The way I implemented it is by passing the additionalPickerEvents containing the web events through props from the index.js entrypoint. In the Picker, I declared additionalPickerEvents as a defaultProp with an empty function, so we don’t have to pass anything from the native entrypoint.

I refactored all of the setState({isOpen: bool}) calls into setters like in your example. I did not introduce an updateAndClose() function, as the native implementation does not handle both operations in a single event, so it would have only been used for web.

Again, checks out on all platforms.

Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me. Just a couple of places where I think we could use a bound function instead of an anonymous arrow function.

@redstar504
Copy link
Contributor Author

@marcaaron Requested changes pushed!

@marcaaron marcaaron self-requested a review March 10, 2023 19:57
marcaaron
marcaaron previously approved these changes Mar 10, 2023
Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't test but code LGTM so approving. All yours @thesahindia.

Comment on lines 160 to 170
setIsOpen() {
this.setState({
isOpen: true,
});
}

setIsClosed() {
this.setState({
isOpen: false,
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The names here sounds confusing. When I looked at them I felt that we have two different state (isClosed and isOpen) I think we should change the names for these methods or we can just use one method (setIsOpen) and pass true/false as argument.

What do you guys think?

cc: @marcaaron @redstar504

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I think we should clarify what that state variable actually controls. Since it is only responsible for enabling and disabling the highlight, we can make it more understandable by using an isHighlighted state variable, and calling enableHighlight and disableHighlight to control it.

import Text from '../Text';
import styles from '../../styles/styles';
import themeColors from '../../styles/themes/default';
import {ScrollContext} from '../ScrollViewWithContext';

const propTypes = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create a new file pickerPropTypes.js and define all the props there except additionalPickerEvents. Let's import the propTypes and defaultProps from pickerPropTypes.js and use them at native and index.js too. Here's an example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since no props are specifically referenced in the platform-specific wrappers, it might be unnecessary to perform validation there before passing them to the BasePicker. However, if this is an established pattern in the codebase, it would be a good idea to follow that with our changes as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we are doing it but I am not sure if it's needed. I think @marcaaron would know more about it or we can ask at expensify-open-source

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I don't feel too passionate about this one. Or at least I can't think of a situation where it would help because the props are just getting passed straight to the BasePicker. If there was some prop validation warning we would see it either way.

@redstar504
Copy link
Contributor Author

Thanks for the review @thesahindia. I have added your requested changes to the latest commit.

@thesahindia
Copy link
Member

thesahindia commented Mar 13, 2023

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified tests pass on all platforms & I tested again on:
    • Android / native
    • Android / Chrome
    • iOS / native
    • iOS / Safari
    • MacOS / Chrome / Safari
    • MacOS / Desktop
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Web
Screen.Recording.2023-03-14.at.12.41.51.AM.mov
Mobile Web - Chrome
Screen.Recording.2023-03-14.at.1.21.04.AM.mov
Mobile Web - Safari
Screen.Recording.2023-03-14.at.1.23.21.AM.mov
Desktop
Screen.Recording.2023-03-14.at.12.41.04.AM.mov
iOS
Screen.Recording.2023-03-14.at.1.25.37.AM.mov
Android
Screen.Recording.2023-03-14.at.1.10.13.AM.mov

@thesahindia
Copy link
Member

thesahindia commented Mar 13, 2023

Looks good! Just one console error -
Steps:-

  1. Reload the page
  2. Go to settings > workspaces > click on any workspace
  3. Click on workspace avatar

Screenshot 2023-03-14 at 1 27 29 AM

@redstar504
Copy link
Contributor Author

@thesahindia

The error is due to the prop validation we've added in the entrypoints. Adding propTypes directly to the component created by forwardRef does not validate as expected. It seems that we would have to wrap the BasePicker, do the prop validation and then wrap it again using forwardRef. This would be unnecessary, since all of the props are already being validated in the BasePicker. There is no need to validate them in the entrypoints as well.

For example, this works but does not provide any benefit:

// index.js
import {defaultProps, propTypes} from './pickerPropTypes';

// eslint-disable-next-line react/jsx-props-no-spreading
const Picker = props => <BasePicker {...props} additionalPickerEvents={additionalPickerEvents} />;

Picker.propTypes = propTypes;
Picker.defaultProps = defaultProps;

// eslint-disable-next-line react/jsx-props-no-spreading
export default forwardRef((props, ref) => <Picker {...props} innerRef={ref} />);

Using shared propTypes looks to be common when there are multiple entrypoints that do not wrap an underlying component. It's purpose would be to give them a common interface to conform to.

I suggest that we rollback this change as it is not necessary for our scenario.

@redstar504
Copy link
Contributor Author

redstar504 commented Mar 14, 2023

@thesahindia I reverted shared prop types due to the reasons described in my last comment. Props are still validated as expected through the base Picker component, and there are no console errors. So we should be good.

thesahindia

This comment was marked as outdated.

Copy link
Member

@thesahindia thesahindia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take back what I said. It didn't test well. I was checking other pages to confirm that all the functionalities are working as expected. It is not working correctly. Not getting the error message for the picker. @redstar504, can you look into it?

I am on a slow internet so I couldn't upload the video. You can try reproducing it at "Add debit card page" or any other page where we are validating.

@redstar504
Copy link
Contributor Author

@thesahindia Great job catching that. We needed to pass the ref all the way down to the base component by that name to continue forwarding it, and only then it's passed to the RNPickerSelect as innerRef. It should be fixed now.

@redstar504 redstar504 force-pushed the Brayden-PickerIndicator branch from ebd3673 to 2924efb Compare March 14, 2023 15:42
@redstar504 redstar504 force-pushed the Brayden-PickerIndicator branch from 2924efb to f956e52 Compare March 14, 2023 15:43
Copy link
Member

@thesahindia thesahindia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! It works well.

cc: @marcaaron

Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job here overall and LGTM. Thanks @thesahindia for the comments and testing 🙇

@marcaaron marcaaron merged commit 38defc6 into Expensify:main Mar 15, 2023
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/marcaaron in version: 1.2.85-0 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

@OSBotify
Copy link
Contributor

🚀 Deployed to production by https://github.com/Julesssss in version: 1.2.85-1 🚀

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants