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

refactor: [M3-8501] - AccessSelect Optimization: Use React Hook Form #10952

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from

Conversation

harsh-akamai
Copy link
Contributor

Description 📝

The goal is to see if we can eliminate the number of useState calls we're making in this file and potentially remove the useEffect by using React Hook Form and inferring values from other values.

Changes 🔄

  • Replaced the existing queries with react-query queries and mutations for managing state
  • Used React Hook Form for better state management

Target release date 🗓️

N/A

How to test 🧪

Verification steps

  • Check if the AccessSelect component's functionality is unaffected by the changes

As an Author I have considered 🤔

Check all that apply

  • 👀 Doing a self review
  • ❔ Our contribution guidelines
  • 🤏 Splitting feature into small PRs
  • ➕ Adding a changeset
  • 🧪 Providing/Improving test coverage
  • 🔐 Removing all sensitive information from the code and PR description
  • 🚩 Using a feature flag to protect the release
  • 👣 Providing comprehensive reproduction steps
  • 📑 Providing or updating our documentation
  • 🕛 Scheduling a pair reviewing session
  • 📱 Providing mobile support
  • ♿ Providing accessibility support

@harsh-akamai harsh-akamai self-assigned this Sep 17, 2024
@harsh-akamai harsh-akamai requested a review from a team as a code owner September 17, 2024 12:29
@harsh-akamai harsh-akamai requested review from mjac0bs and abailly-akamai and removed request for a team September 17, 2024 12:29
@harsh-akamai harsh-akamai added the Help Wanted Teamwork makes the dream work! label Sep 17, 2024
@abailly-akamai
Copy link
Contributor

@harsh-akamai can you make sure to fix your unit tests before people review the PR?

@harsh-akamai
Copy link
Contributor Author

@abailly-akamai I have fixed the failing unit tests

Copy link

github-actions bot commented Sep 20, 2024

Coverage Report:
Base Coverage: 86.95%
Current Coverage: 86.95%

Copy link
Contributor

@abailly-akamai abailly-akamai left a comment

Choose a reason for hiding this comment

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

Thanks for working on this. The change makes sense and the code cleanup looks good, and is well self documented and tested

There is a state issue in the form however. The cors toggle shows always as enabled on page load, no matter it's value.

Screen.Recording.2024-09-27.at.09.12.56.mov

Looks like e2e test failures are flakes. You may want to rebase your PRA again to get the latest from develop since those have been fixed there i believe

@harsh-akamai harsh-akamai removed the Help Wanted Teamwork makes the dream work! label Sep 30, 2024
Copy link
Contributor

@abailly-akamai abailly-akamai left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for addressing the fix.

Approving, and leaving a few optional UI improvements to consider, out of the scope but we may as well tackle them now:

Screenshot 2024-10-01 at 09 14 19

Copy link
Contributor

@jaalah-akamai jaalah-akamai left a comment

Choose a reason for hiding this comment

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

Really nice job here! Just some minor changes and this is looking 🔥

Comment on lines 174 to 178
onChange={(_, selected) => {
if (selected) {
field.onChange(selected.value);
}
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

We can just set the value on the onChange itself

Suggested change
onChange={(_, selected) => {
if (selected) {
field.onChange(selected.value);
}
}}
onChange={(_, selected: { label: string; value: ACLType }) => {
if (selected) {
setValue('acl', selected.value);
}
}}

<Toggle
{...field}
checked={field.value}
disabled={bucketAccessIsFetching || objectAccessIsFetching}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
disabled={bucketAccessIsFetching || objectAccessIsFetching}
disabled={bucketAccessIsFetching || objectAccessIsFetching}
onChange={(e) => setValue('cors_enabled', e.target.checked)}

Comment on lines 93 to 96
defaultValues: {
acl: 'private',
cors_enabled: true,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

In correlation to changes from removing useEffect

Suggested change
defaultValues: {
acl: 'private',
cors_enabled: true,
},
defaultValues

import { capitalize } from 'src/utilities/capitalize';
import { getErrorStringOrDefault } from 'src/utilities/errorUtils';

import { bucketACLOptions, objectACLOptions } from '../utilities';
import { copy } from './AccessSelect.data';

import type {
ACLType,
Copy link
Contributor

Choose a reason for hiding this comment

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

We'll need this back with my suggested changes

control,
formState: { errors, isSubmitting },
handleSubmit,
reset,
Copy link
Contributor

Choose a reason for hiding this comment

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

Replacing reset with setValue for more granular control in new approach

Suggested change
reset,
setValue,

Comment on lines 101 to 114
React.useEffect(() => {
const data = variant === 'object' ? objectAccessData : bucketAccessData;
if (data) {
const { acl } = data;
// Don't show "public-read-write" for Objects here; use "custom" instead
// since "public-read-write" Objects are basically the same as "public-read".
const _acl =
variant === 'object' && acl === 'public-read-write' ? 'custom' : acl;
const cors_enabled = isUpdateObjectStorageBucketAccessPayload(data)
? data.cors_enabled ?? undefined
: true;
reset({ acl: _acl || undefined, cors_enabled });
}
}, [bucketAccessData, objectAccessData, variant, reset]);
Copy link
Contributor

Choose a reason for hiding this comment

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

No idea what happened to my previous comments, so I'll just restate things.

We can remove this useEffect and use the internals to calculate the defaultValues based on the latest API data.

const data = variant === 'object' ? objectAccessData : bucketAccessData;

  const defaultValues = React.useMemo(() => {
    if (data) {
      const { acl } = data;
      const _acl =
        variant === 'object' && acl === 'public-read-write' ? 'custom' : acl;
      const cors_enabled = isUpdateObjectStorageBucketAccessPayload(data)
        ? data.cors_enabled ?? true
        : true;
      return { acl: _acl as ACLType, cors_enabled };
    }
    return { acl: 'private' as ACLType, cors_enabled: true };
  }, [data, variant]);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think removing useEffect might not solve the issue in this case since the useForm hook reads the defaultValues only on the initial render. Updating defaultValues to the values returned from the api wouldn't update the form state. We will have to use the reset() to update the form and I feel we will have to run reset() inside a useEffect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like passing the formValues to the values parameter of useForm() removes the necessity of useEffect(). I have pushed these changes in the latest commit(9a2430f)

Copy link
Contributor

@mjac0bs mjac0bs left a comment

Choose a reason for hiding this comment

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

Coming late to this PR, but wanted to prevent it from getting stale. I didn't notice any major regressions in the Access Select and test are passing. I did notice a minor regression in loading state (see video clips).

Also re-requesting Jaalah since this PR is blocked by requested changes that, I think, have all been addressed now.

}
}}
placeholder={
bucketAccessIsFetching || objectAccessIsFetching
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't seem to be working as expected. We have a small regression in the loading state but I wasn't seeing why right off. We have the loading prop and the fetching state of the two queries. Autocomplete has the loadingText prop, but I don't think that makes a difference.

Prod This Branch
autocompleteLoadingState.mov
autocompleteNoLoadingState.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing this out! The issue stems from setting default values for the form. One possible workaround is to add an option to the Options array with the placeholder text 'Loading access..', though I am uncertain if this would be the most optimal solution for maintaining clean and efficient code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Add'tl Approval Needed Waiting on another approval! Ready for Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants