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

Fix / TVOD infinite loop and render optimizations #288

Conversation

ChristiaanScheermeijer
Copy link
Collaborator

Description

This PR fixes an infinite render loop when opening the Choose Offer modal for a JWP TVOD platform. This was caused by the clientOffers being constructed each render while being a dependency in the useOffers hook.

Besides that, for a TVOD platform, the clientOffer resulted in ['null'] when not set. This causes the useOffers hook to request non-existing offers for JWP and Cleeng.

The other commit fixes some unnecessary renders in the Choose Offer form caused by depending on the location or navigate (which also depends on location) reactive variables.

@github-actions
Copy link

Visit the preview URL for this PR (updated for commit 309791d):

https://ottwebapp--pr288-fix-tvod-fix-infinit-qgcetuia.web.app

(expires Sat, 24 Jun 2023 15:06:39 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c198f8a3a199ba8747819f7f1e45cf602b777529

@@ -55,6 +57,7 @@ const useEntitlement: UseEntitlement = (playlistItem) => {
queryFn: () => checkoutService?.getEntitlements({ offerId }, sandbox),
enabled: !!playlistItem && !!user && !!offerId && !isPreEntitled,
refetchOnMount: 'always' as const,
notifyOnChangeProps,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason we can't just use string literals here?

Suggested change
notifyOnChangeProps,
['data', 'isLoading'],

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Without the as const modifiers, the type results in string[] and is not accepted by react-query.

If I use ['data', 'isLoading'] as const the type results in readonly ['data', 'isLoading'] and is also not accepted by react-query.

This does work but is not much cleaner IMHO

const notifyOnChangeProps: QueryObserverOptions['notifyOnChangeProps'] = ['data', 'isLoading'];

return [`${integrations.jwp.assetId}`];
}

if (isCleeng && integrations.cleeng?.monthlyOffer && integrations.cleeng?.yearlyOffer) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we try to support monthly OR yearly as well?

const currentPeriod = subscription?.period;
const closeModal = useEventCallback((replace = false) => {
navigate(removeQueryParam(location, 'u'), { replace });
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you need dependencies on navigate and location here and below?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It should be in a regular useCallback, but not in the useEventCallback.

We've found that when a modal has an effect, memo or callback on the location/navigate properties, all will trigger an update when closing the modal because of the location update.

Because this is hard to discover, we've chosen to wrap these dependant functions with useEventCallback to ensure functions depending will not update unnecessarily (and possibly cause issues).

For example, this useEffect:

useEffect(() => {
    // close auth modal when there are no offers defined in the config
    if (!isLoading && !offers.length) {
      closeModal(true);
    }
  }, [isLoading, offers, closeModal]);

This effect closes the modal (only once) based on the reactive variables isLoading and offers. The closeModal is still considered a reactive variable, but never updates because wrapped in useEventCallback.

The problem without the useEventCallback is that we can't ensure that this effect is only running when isLoading or offers are changed. Because it will also run when location changes (after a navigate).

@@ -41,20 +42,24 @@ const AccountModal = () => {
} = config;
const isPublicView = viewParam && PUBLIC_VIEWS.includes(viewParam);

const toLogin = useEventCallback(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question if we need dependencies on navigate and location?

@RCVZ RCVZ merged commit 3e6baff into feat/jwp-sprint-2023-2 May 30, 2023
@ChristiaanScheermeijer ChristiaanScheermeijer deleted the fix/tvod-fix-infinite-loop-and-render-optimizations branch May 30, 2023 09:07
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.

3 participants