Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.57k stars 2.92k forks source link

[$250] Tags - State field is not auto selected when there is only one tag #52137

Open IuliiaHerets opened 2 weeks ago

IuliiaHerets commented 2 weeks ago

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: 9.0.58-1 Reproducible in staging?: Y Reproducible in production?: N If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: Y If this was caught during regression testing, add the test name, ID and link from TestRail: https://expensify.testrail.io/index.php?/tests/view/5188086 Email or phone of affected tester (no customers): applausetester+khcategory18@applause.expensifail.com Issue reported by: Applause Internal Team

Action Performed:

Precondition:

  1. Launch hybrid or ND app.
  2. Go to workspace chat in which dependent multi tags are set up.
  3. Tap + > Submit expense > Manual.
  4. Enter amount > Next.

Expected Result:

State field will be auto selected with the only one tag because "Members must tag all expenses" in Tags settings is enabled. (It is auto selected on staging web and production hybrid).

Actual Result:

State field is not auto selected with the only one tag even when "Members must tag all expenses" in Tags settings is enabled. This issue only happens on Android and iOS app (both hybrid and standalone).

Workaround:

Unknown

Platforms:

Screenshots/Videos

https://github.com/user-attachments/assets/a69be543-24a0-43c4-b69c-8337d8ec2c3a

Bug66568081730914735568!Dependent-_Multi_Level_tags_NEW.csv

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021854535982635221591
  • Upwork Job ID: 1854535982635221591
  • Last Price Increase: 2024-11-14
  • Automatic offers:
    • truph01 | Contributor | 104908657
Issue OwnerCurrent Issue Owner: @hoangzinh
melvin-bot[bot] commented 2 weeks ago

Triggered auto assignment to @strepanier03 (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

melvin-bot[bot] commented 2 weeks ago

Triggered auto assignment to @danieldoglas (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

melvin-bot[bot] commented 2 weeks ago

💬 A slack conversation has been started in #expensify-open-source

github-actions[bot] commented 2 weeks ago

: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:

  1. Identify the pull request that introduced this issue and revert it.
  2. Find someone who can quickly fix the issue.
  3. Fix the issue yourself.
danieldoglas commented 2 weeks ago

@IuliiaHerets can you please post the video for it working in production as well? Thanks!

IuliiaHerets commented 2 weeks ago

@danieldoglas Can you please check the added video? it includes the prod behavior too

danieldoglas commented 2 weeks ago

Oh, I think I got confused because you downloaded both from test flight. Thanks for confirming

truph01 commented 2 weeks ago

Edited by proposal-police: This proposal was edited at 2024-11-11 11:05:40 UTC.

Proposal

Please re-state the problem that we are trying to solve in this issue.

What is the root cause of that problem?

https://github.com/Expensify/App/blob/ef76462dd29427b098d7567ff1a4c119218f5076/src/components/MoneyRequestConfirmationList.tsx#L697

so the useEffect is not called again once the transaction data is available.

What changes do you think we should make in order to solve the problem?

https://github.com/Expensify/App/blob/12233119e9b4793b32ed2c8b38366097a0efc792/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx#L57 we can introduce a new variable to check whether we are loading transaction data:

        const [transaction, transactionResult] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`);
        const [transactionDraft, transactionDraftResult] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`);
        const isLoadingTransaction = isLoadingOnyxValue(transactionResult, transactionDraftResult);

and then pass down this variable to its child.

https://github.com/Expensify/App/blob/12233119e9b4793b32ed2c8b38366097a0efc792/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx#L57 we can introduce a new variable to check whether we are loading transaction data:

        const [transaction, transactionResult] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`);
        const [transactionDraft, transactionDraftResult] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`);
        const isLoadingTransaction = isLoadingOnyxValue(transactionResult, transactionDraftResult);
    // Auto select the tag if there is only one enabled tag and it is required
    useEffect(() => {
        if(isLoadingTransaction){
            return
        }
        ...
    }, [policyTagLists, policyTags, isLoadingTransaction]);

Also, this is our common solution when migrating withOnyx to useOnyx.

Julesssss commented 2 weeks ago

Hey @danieldoglas I decided not to block on this as this is very easy for users to figure out -- simply select it manually as the violation suggests.

I think it can be made external to speed up the fix, we have a decent proposal already. We will also need to locate the regression though. I'm unsubscribing so please tag me if you need me 👋

melvin-bot[bot] commented 2 weeks ago

Job added to Upwork: https://www.upwork.com/jobs/~021854535982635221591

melvin-bot[bot] commented 2 weeks ago

Triggered auto assignment to Contributor-plus team member for initial proposal review - @hoangzinh (External)

klajdipaja commented 2 weeks ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Tag is not auto-selected on submit expense when the workspace has enabled required tags.

What is the root cause of that problem?

Initially, the component renders with transactionID=-1 which is then used in this block to add the required tag: https://github.com/Expensify/App/blob/ef76462dd29427b098d7567ff1a4c119218f5076/src/components/MoneyRequestConfirmationList.tsx#L692-L694. As a consequence you can find on Onyx this key transactionsDraft_-1 which holds only the tag in the value: {tag: 'tst'}

What changes do you think we should make in order to solve the problem?

We need to update this useEffect dependencies to add the transcationId in it in this line: https://github.com/Expensify/App/blob/ef76462dd29427b098d7567ff1a4c119218f5076/src/components/MoneyRequestConfirmationList.tsx#L697 And to avoid creating the onyx entry for the -1 id we should add an early return in the useEffect:

if(transactionID === '-1'){
            return;
        }   

What alternative solutions did you explore? (Optional)

hoangzinh commented 2 weeks ago

Thanks for your proposals. @truph01 @klajdipaja does anyone know why it only happens in native apps? It works for me in Web

klajdipaja commented 2 weeks ago

@hoangzinh I actually tested both the bug and my solution on macOS chrome slighlty differently from the test steps. If I try to do it using the steps in the issue description I can reproduce it only on native but if I try to Submit an expense directly from the Workspace itself then I can reproduce it in Chrome. Here's a recording on chrome:

https://github.com/user-attachments/assets/b258fcf3-b3ef-430a-9f43-1310d4afccd6

I cannot seem to find where exactly the culprit of this behaviour is but since all other useEffects in the same component that use transactionID for similar actions are also adding it in the dependencies I think it's safe to assume that it is needed.

truph01 commented 2 weeks ago

Thanks for your proposals. @truph01 @klajdipaja does anyone know why it only happens in native apps? It works for me in Web

It seems that react-native-onyx behaves slightly differently across platforms (web vs. native). Based on my RCA, try logging the transaction data inside this useEffect: https://github.com/Expensify/App/blob/ef76462dd29427b098d7567ff1a4c119218f5076/src/components/MoneyRequestConfirmationList.tsx#L682

on both native and web platforms to compare the results. In native, the transaction is undefined on the first render, whereas in web, it already holds a defined value.

hoangzinh commented 2 weeks ago

I think it's caused by this migration withOnyx PR https://github.com/Expensify/App/pull/51244

Differently from useOnyx(), withOnyx() will delay the rendering of the wrapped component until all keys/entities have been fetched and passed to the component, this can be convenient for simple cases

[Ref link](https://github.com/Expensify/react-native-onyx#:~:text=Differently%20from%20useOnyx()%2C%20withOnyx()%20will%20delay%20the%20rendering%20of%20the%20wrapped%20component%20until%20all%20keys/entities%20have%20been%20fetched%20and%20passed%20to%20the%20component%2C%20this%20can%20be%20convenient%20for%20simple%20cases)

hoangzinh commented 2 weeks ago

I lean toward @klajdipaja's solution. @truph01's solution will cause regression bugs if policyTagLists, policyTags are updated by Pusher events

truph01 commented 2 weeks ago

@hoangzinh I added the alternative solution to my proposal

truph01 commented 2 weeks ago

@hoangzinh Also, did you test this solution and it works well, right? I tested from my side, but it does not work in native. Please correct me if I am wrong.

Proposal updated

hoangzinh commented 2 weeks ago

@truph01 Thanks for the updates. Yes, I did. It worked for me, and it aligns with our root cause.

Uhm, after considering, I still think adding transactionID to the dependency list is better. It's simpler and works in the react way if transactionID is updated

truph01 commented 2 weeks ago

it aligns with our root cause

The root cause isn’t simply that transaction data is initially undefined, but rather that it hasn’t been loaded yet, which makes the data undefined until it’s fully retrieved. Recognizing this helps us understand that transaction data can appear undefined during loading, potentially leading to similar issues in the future. To address this more generally, a loading indicator should be shown if isLoadingTransaction is true in here:

    if (isLoadingTransaction) {
        return <FullScreenLoadingIndicator />;
    }

This approach suggests that the proposed solution serves as a temporary workaround rather than a direct fix for the root issue.

Additionally, if my root cause analysis is correct, you’ll notice that this proposal doesn’t address it directly, which is a significant factor when selecting a solution as noted in this issue."

klajdipaja commented 2 weeks ago

It is a widely used approach in the app that when the onyx value is not found we check for -1 and that is also used in many other occurrences in the IOU flow.

If we wanted to acknowledge the fact that the Onyx transaction is loading then we would need to do that at the root of the issue in WithFullTransactionOrNotFound and expose that as a property of the HCO component so that all wrapper components can handle it as they wish.

        return (
            <WrappedComponent
                // eslint-disable-next-line react/jsx-props-no-spreading
                {...(props as TProps)}
                transactionLoading={shouldUseTransactionDraft ? transactionDraftLoading : transactionLoading}
                transaction={shouldUseTransactionDraft ? transactionDraft : transaction}
                ref={ref}
            />
        );

If we check for the loader only in IOURequestStepConfirmation then we still will end up in the future having to go through long debugging work to understand the edge case. But t if we do this change we have to align all components instead of the -1 check to do the transactionLoading check. That sounds like a major change to me to a minor problem.

truph01 commented 2 weeks ago

If we wanted to acknowledge the fact that the Onyx transaction is loading then we would need to do that at the root of the issue in WithFullTransactionOrNotFound and expose that as a property of the HCO component so that all wrapper components can handle it as they wish.

I already mentioned it in my alternative solution

truph01 commented 2 weeks ago

Proposal updated

hoangzinh commented 1 week ago

After considering proposals, I think @truph01's proposal looks good to me. Showing a loading indicator seems to fix this issue and other similar issues properly.

Link to proposal https://github.com/Expensify/App/issues/52137#issuecomment-2461591806

🎀👀🎀 C+ reviewed

melvin-bot[bot] commented 1 week ago

Triggered auto assignment to @francoisl, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

melvin-bot[bot] commented 1 week ago

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

melvin-bot[bot] commented 1 week ago

📣 @truph01 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link Upwork job Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻 Keep in mind: Code of Conduct | Contributing 📖

melvin-bot[bot] commented 1 week ago

@francoisl, @danieldoglas, @hoangzinh, @strepanier03, @truph01 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

truph01 commented 1 week ago

PR is ready