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

feat: add value-independent hook for setting online status message [LIBS-369] #1363

Merged
merged 4 commits into from
Dec 12, 2023

Conversation

KaiVandivier
Copy link
Contributor

@KaiVandivier KaiVandivier commented Dec 11, 2023

Implements LIBS-369

Key features

Adds individual hooks and contexts for getting and setting the online status message. As such, consumers of useSetOnlineStatusMessage won't need to rerender when the message value changes

  1. useOnlineStatusMessageValue()
  2. useSetOnlineStatusMessage()

Notes

  • I consider these changes a feat because the existing useOnlineStatusMessage hook is relatively unchanged in behavior, but there are now two more optimal hooks available
  • These changes are backwards compatible -- consumers don't need to change to one of the new hooks
  • I moved the types around a little bit
  • Here are consumers that might benefit from switching to using the new hooks:
    • Aggregate Data Entry app (edit: this actually uses the value too, never mind)
    • UI Header Bar (actually... probably fine as-is, since the set function won't cause unnecessary rerenders)

Checklist

  • Have written Documentation
  • Has tests coverage -- the existing test works as a small integration test

@KaiVandivier KaiVandivier changed the title feat: add value-indepent hook for setting online status message [LIBS-369] feat: add value-independent hook for setting online status message [LIBS-369] Dec 11, 2023
@KaiVandivier KaiVandivier requested a review from a team December 11, 2023 14:34
@Mohammer5
Copy link
Contributor

I did change the return value of onlineStatusMessage to be null instead of undefined to distinguish between "not yet set" and "missing its context provider" conditions, but I doubt think this will break anything. The existing consumers I know of (see below) don't mind

This is technically a breaking change. IMO we should always bump the major version, even when we think no lib consumer will break. In case it does affects a consumer, it'd be a PITA to get to the bottom of this..

If you agree with this, we'll have two choices: Either separate that into a separate PR and discuss that particular change itself or make this PR introduce a breaking change. (I'm in favor of the former, but in this case it's such a small thing that I don't care too much)

Comment on lines 46 to 50
if (setOnlineStatusMessage === undefined) {
throw new Error(
'useSetOnlineStatusMessage must be used within an OnlineStatusMessageProvider'
)
}
Copy link
Member

@Birkbjo Birkbjo Dec 11, 2023

Choose a reason for hiding this comment

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

I think setOnlineStatusMessage will be the default value of the context - eg. ```() => undefined```` and not undefined if there's no context in the tree? But see my comment below, not sure if this is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah true - I admit that these checks are a bit of an automatic habit 🤦‍♂️ I'll remove them as you suggested in your other comment

Comment on lines 33 to 38
// note: value is initialized to `null` in provider, not undefined
if (onlineStatusMessage === undefined) {
throw new Error(
'useOnlineStatusMessageValue must be used within an OnlineStatusMessageProvider'
)
}
Copy link
Member

@Birkbjo Birkbjo Dec 11, 2023

Choose a reason for hiding this comment

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

This could cause issues if you manually set the status to undefined. Subsequent calls to this would then throw.

So if we were to do this, I think we should prevent undefined being passed to setOnlineStatusMessage. But that would definitely be a breaking change. However, if we just want to check that it's not the default, we could initialize it to a Symbol.

But this is all rendered in the app-shell, right? So this might just create more complexity than it's worth. And calling setOnlineStatusMessage without a context is fine, since it's just a noop.

So in my opinion I think we could just remove these checks, which would work-around the "potential breaking change".

Initializing with null or undefined then doesn't matter, and was never part of the API contract. And no functionality would change. The only problem would be these checks if we kept it like this (mostly due to being able to set it as undefined through setOnlineStatusMessage.

Copy link
Member

@Birkbjo Birkbjo Dec 11, 2023

Choose a reason for hiding this comment

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

If we really wanted to fail early, I think it would look something like this:

const defaultOnlineStatusMessage = Symbol("defaultStatusMessage");
const OnlineStatusMessageValueContext = React.createContext<
  ReactNode | typeof defaultOnlineStatusMessage
>(defaultOnlineStatusMessage);

export const useOnlineStatusMessageValue = () => {
  const onlineStatusMessage = useContext(OnlineStatusMessageValueContext);

  if (onlineStatusMessage === defaultOnlineStatusMessage) {
    throw new Error(
      "useOnlineStatusMessageValue must be used within an OnlineStatusMessageProvider"
    );
  }
  // this should be inferred to be a ReactNode
  return onlineStatusMessage;
};

useSetOnlineStatusMessage, would be similiar but extracting the "noop" default function to variable and check for that equality.

I think this could be done without a breaking change, since you would keep the public API the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a solid solution, but I just went with removing the undefined checks to keep it simple -- I think you're right that the app adapter kinda guarantees the provider will be there

@KaiVandivier KaiVandivier merged commit a2831e6 into master Dec 12, 2023
9 checks passed
@KaiVandivier KaiVandivier deleted the libs-369-optimize-online-status-message branch December 12, 2023 13:28
dhis2-bot added a commit that referenced this pull request Dec 12, 2023
# [3.10.0](v3.9.4...v3.10.0) (2023-12-12)

### Features

* add value-independent hook for setting online status message [LIBS-369] ([#1363](#1363)) ([a2831e6](a2831e6))
@dhis2-bot
Copy link
Contributor

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

Successfully merging this pull request may close these issues.

4 participants