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

[MPDX-8393] Add useUserPreference hook #1146

Merged
merged 9 commits into from
Oct 21, 2024
Merged

[MPDX-8393] Add useUserPreference hook #1146

merged 9 commits into from
Oct 21, 2024

Conversation

canac
Copy link
Contributor

@canac canac commented Oct 18, 2024

Description

Create a new useUserPreference hook that is as ergonomic as useState but syncs its value with a user preference.

Usage:

const [value, setValue] = useUserPreference({ key: 'hidden_tabs', defaultValue: [] });

Features:

  • Calling setValue updates value immediately without having to wait for the server to respond.
  • If defaultValue isn't a string, the value is transparently serialized and deserialized as JSON.
  • If another component loaded all options with the userOptions query, this hook can extract the relevant option from the Apollo cache immediately before the userOption query returns.

Depends on https://github.com/CruGlobal/mpdx_api/pull/2872

I updated the code to use this new hook for the setup_position, and flows (the flows columns) preferences to prove its usefulness. It could also be used for the view mode preference once #1131 is merged. I will also use it in the upcoming PR for the dismissible beacon.

Checklist:

  • I have given my PR a title with the format "MPDX-(JIRA#) (summary sentence max 80 chars)"
  • I have applied the appropriate labels. (Add the label "On Staging" to get the branch automatically merged into staging.)
  • I have requested a review from another person on the project

@canac canac added the Preview Environment Add this label to create an Amplify Preview label Oct 18, 2024
@canac canac requested a review from dr-bizz October 18, 2024 20:45
@canac canac self-assigned this Oct 18, 2024
Copy link
Contributor

Preview branch generated at https://8393-user-preference.d3dytjb8adxkk5.amplifyapp.com

Comment on lines +101 to +115
const temp = [...flowOptions];
if (originIndex > -1) {
temp[originIndex] = {
...temp[originIndex],
statuses: temp[originIndex].statuses.filter(
(status) => status !== draggedStatus,
),
};
}
if (destinationIndex > -1) {
temp[destinationIndex] = {
...temp[destinationIndex],
statuses: [...temp[destinationIndex].statuses, draggedStatus],
};
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before this was updating cloning the array of flow options but still modifying the original column. This clones the column too before updating it.

@@ -0,0 +1,15 @@
query UserOption($key: String!) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This query and mutation doesn't need to load the id field anymore because I changed the cache to use the key to generate Options' unique id.

@@ -80,6 +82,15 @@ export const createCache = () =>
people: paginationFieldPolicy,
tasks: paginationFieldPolicy,
userNotifications: paginationFieldPolicy,
// When loading a user option, look it up from the cache by its key
userOption: {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This makes it so that if some other component loaded all the user options with the userOptions query, the userOption (singular) query can pull the option out of the cache by its key instead of having to wait for it to load.

Copy link
Contributor

github-actions bot commented Oct 21, 2024

Bundle sizes [mpdx-react]

Compared against d59ffdd

No significant changes found

Copy link
Contributor

@dr-bizz dr-bizz left a comment

Choose a reason for hiding this comment

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

This is great!

}

if (typeof defaultValue === 'string') {
setValue((data.userOption.value ?? defaultValue) as T);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you not check if data.userOption.value needs to be pared as JSON here like you do below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This hook assumes that if defaultValue is a string, the component just needs to save a simple string as the preference. For example the view mode, which could be "list", "flows", or "map". If defaultValue isn't an object, it assumes that the component needs to save an object or array as the preference and does the automatic JSON serialization/deserialization. This branch is the simple string code path.

src/hooks/useUserPreference.ts Show resolved Hide resolved
@canac canac force-pushed the 8393-user-preference branch from 9c41fa4 to 0401c51 Compare October 21, 2024 19:33
@canac canac force-pushed the 8393-user-preference branch from 0401c51 to d830fb2 Compare October 21, 2024 20:38
@canac canac merged commit 86d678b into main Oct 21, 2024
17 of 18 checks passed
@canac canac deleted the 8393-user-preference branch October 21, 2024 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Preview Environment Add this label to create an Amplify Preview
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants