From 62c209a6fe810e704d024c5e9f4eefb7605b657d Mon Sep 17 00:00:00 2001 From: Michael Peters Date: Sat, 22 Jan 2022 19:34:29 -0600 Subject: [PATCH] don't call onFetch when the fetch function returns null --- .../webapp/elements/lists/member-list.tsx | 2 +- .../elements/require/guild-subscriptions.ts | 45 ++++++++++--------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/client/webapp/elements/lists/member-list.tsx b/src/client/webapp/elements/lists/member-list.tsx index 9eec3a2..79595d1 100644 --- a/src/client/webapp/elements/lists/member-list.tsx +++ b/src/client/webapp/elements/lists/member-list.tsx @@ -26,7 +26,7 @@ const MemberList: FC = (props: MemberListProps) => { if (!isNonNullAndHasValue(membersResult)) { return
Loading members...
} - LOG.debug(`drawing ${membersResult.value.length} members`); + //LOG.debug(`drawing ${membersResult.value.length} members`); return membersResult.value.map((member: Member) => ); }, [ guild, membersResult, membersFetchError ]); diff --git a/src/client/webapp/elements/require/guild-subscriptions.ts b/src/client/webapp/elements/require/guild-subscriptions.ts index fa6675f..0244275 100644 --- a/src/client/webapp/elements/require/guild-subscriptions.ts +++ b/src/client/webapp/elements/require/guild-subscriptions.ts @@ -96,10 +96,11 @@ interface MultipleEventMappingParams< * @param subscriptionParams Event callback functions * @param fetchFunc Function that can be called to fetch the data for the subscription. This function will be called automatically if it is changed. * Typically, this function will be set up in a useCallback with a dependency on at least the guild. + * If the fetch function returns null, this will not call "onFetch". This allows results to stay until the guilds are updated. */ function useGuildSubscriptionEffect( subscriptionParams: EffectParams, - fetchFunc: () => Promise + fetchFunc: () => Promise ): [ fetchRetryCallable: () => Promise ] { const { guild, onFetch, onFetchError, bindEventsFunc, unbindEventsFunc } = subscriptionParams; @@ -114,6 +115,7 @@ function useGuildSubscriptionEffect( const value = await fetchFunc(); if (!isMounted.current) return; if (guildRef.current !== guild) return; // Don't even call onFetch if we changed guilds. TODO: Test this + if (!value) return; // we decided not to fetch, typically since there are conflicting guilds onFetch(value, guild); } catch (e: unknown) { LOG.error('error fetching for subscription', e); @@ -152,7 +154,7 @@ function useGuildSubscriptionEffect( function useSingleGuildSubscription( guild: CombinedGuild, eventMappingParams: SingleEventMappingParams, - fetchFunc: () => Promise + fetchFunc: () => Promise ): [lastResult: SubscriptionResult | null, fetchError: unknown | null] { const { updatedEventName, updatedEventArgsMap, conflictEventName, conflictEventArgsMap } = eventMappingParams; @@ -219,7 +221,7 @@ function useMultipleGuildSubscription< >( guild: CombinedGuild, eventMappingParams: MultipleEventMappingParams, - fetchFunc: () => Promise + fetchFunc: () => Promise ): [ fetchRetryCallable: () => Promise, lastResult: SubscriptionResult | null, @@ -337,7 +339,7 @@ function useMultipleGuildSubscriptionScrolling< eventMappingParams: MultipleEventMappingParams, maxElements: number, maxFetchElements: number, - fetchFunc: () => Promise, + fetchFunc: () => Promise, fetchAboveFunc: ((reference: T) => Promise), fetchBelowFunc: ((reference: T) => Promise), ): [ @@ -588,13 +590,14 @@ export function useGuildMetadataSubscription(guild: CombinedGuild) { export function useResourceSubscription(guild: CombinedGuild, resourceId: string | null, resourceIdGuild: CombinedGuild | null) { const fetchResourceFunc = useCallback(async () => { //LOG.silly('fetching resource for subscription (resourceId: ' + resourceId + ')'); + // Note: Returning null skips the load. This will prevent a null resourceResult if (resourceId === null) return null; if (resourceIdGuild === null) return null; if (resourceIdGuild !== guild) return null; const fetchResource = await guild.fetchResource(resourceId); return fetchResource; }, [ guild, resourceIdGuild, resourceId ]); // Explicitly do NOT want lastFetchResource since it would cause a re-fetch after fetching successfully - return useSingleGuildSubscription(guild, { + return useSingleGuildSubscription(guild, { updatedEventName: 'update-resource', updatedEventArgsMap: (resource: Resource) => resource, conflictEventName: 'conflict-resource', @@ -604,7 +607,7 @@ export function useResourceSubscription(guild: CombinedGuild, resourceId: string export function useSoftImageSrcResourceSubscription(guild: CombinedGuild, resourceId: string | null, resourceIdGuild: CombinedGuild | null): [ imgSrc: string, - resourceResult: { value: Resource | null, guild: CombinedGuild } | null, + resourceResult: SubscriptionResult | null, fetchError: unknown | null ] { const [ resourceResult, fetchError ] = useResourceSubscription(guild, resourceId, resourceIdGuild); @@ -613,7 +616,7 @@ export function useSoftImageSrcResourceSubscription(guild: CombinedGuild, resour async () => { //LOG.debug(`Fetching soft imgSrc for g#${guild.id} r#${resource?.id ?? ''}`, { fetchError }); if (fetchError) return './img/error.png'; - if (!resourceResult || !resourceResult.value) return './img/loading.svg'; + if (!resourceResult) return './img/loading.svg'; return await ElementsUtil.getImageSrcFromBufferFailSoftly(resourceResult.value.data); }, './img/loading.svg', @@ -642,7 +645,9 @@ export function useChannelsSubscription(guild: CombinedGuild) { export function useMembersSubscription(guild: CombinedGuild) { const fetchMembersFunc = useCallback(async () => { - return await guild.fetchMembers(); + const members = await guild.fetchMembers(); + return members; + //return await guild.fetchMembers(); }, [ guild ]); return useMultipleGuildSubscription(guild, { newEventName: 'new-members', @@ -658,26 +663,27 @@ export function useMembersSubscription(guild: CombinedGuild) { } export function useSelfMemberSubscription(guild: CombinedGuild): [ - selfMemberResult: { value: Member | null - guild: CombinedGuild } | null + selfMemberResult: SubscriptionResult | null ] { const [ _fetchRetryCallable, membersResult, _fetchError ] = useMembersSubscription(guild); // TODO: Show an error if we can't fetch and allow retry - const selfMember = useMemo(() => { - if (membersResult && membersResult.value) { + const [ selfMemberResult, setSelfMemberResult ] = useState | null>(null); + + useEffect(() => { + if (isNonNullAndHasValue(membersResult) && membersResult.guild === guild) { const member = membersResult.value.find(m => m.id === guild.memberId); if (!member) { - LOG.warn('Unable to find self in members'); - return null; + LOG.warn('unable to find self in members'); + setSelfMemberResult({ value: null, guild: membersResult.guild }); + } else { + setSelfMemberResult({ value: member, guild: membersResult.guild }); } - return member; } - return null; - }, [ guild.memberId, membersResult ]); + }, [ membersResult ]); - return [ membersResult ? { value: selfMember, guild: membersResult.guild } : null ]; + return [ selfMemberResult ]; } export function useTokensSubscription(guild: CombinedGuild) { @@ -703,8 +709,7 @@ export function useMessagesScrollingSubscription(guild: CombinedGuild, channel: const maxElements = Globals.MAX_CURRENT_MESSAGES; const fetchMessagesFunc = useCallback(async () => { if (guild !== channelGuild) { - LOG.debug('not loading messages from guild differences'); - return []; + return null; // Note: This skips the load so that we don't have to clear the message list } return await guild.fetchMessagesRecent(channel.id, maxFetchElements); }, [ guild, channelGuild, channel.id, maxFetchElements ]);