don't call onFetch when the fetch function returns null

This commit is contained in:
Michael Peters 2022-01-22 19:34:29 -06:00
parent 9a5e5d822e
commit 62c209a6fe
2 changed files with 26 additions and 21 deletions

View File

@ -26,7 +26,7 @@ const MemberList: FC<MemberListProps> = (props: MemberListProps) => {
if (!isNonNullAndHasValue(membersResult)) {
return <div className="members-loading">Loading members...</div>
}
LOG.debug(`drawing ${membersResult.value.length} members`);
//LOG.debug(`drawing ${membersResult.value.length} members`);
return membersResult.value.map((member: Member) => <MemberElement key={guild.id + member.id} guild={guild} member={member} memberGuild={membersResult.guild} />);
}, [ guild, membersResult, membersFetchError ]);

View File

@ -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<T>(
subscriptionParams: EffectParams<T>,
fetchFunc: () => Promise<T>
fetchFunc: () => Promise<T | null>
): [ fetchRetryCallable: () => Promise<void> ] {
const { guild, onFetch, onFetchError, bindEventsFunc, unbindEventsFunc } = subscriptionParams;
@ -114,6 +115,7 @@ function useGuildSubscriptionEffect<T>(
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<T>(
function useSingleGuildSubscription<T, UE extends keyof Connectable, CE extends keyof Conflictable>(
guild: CombinedGuild,
eventMappingParams: SingleEventMappingParams<T, UE, CE>,
fetchFunc: () => Promise<T>
fetchFunc: () => Promise<T | null>
): [lastResult: SubscriptionResult<T> | null, fetchError: unknown | null] {
const { updatedEventName, updatedEventArgsMap, conflictEventName, conflictEventArgsMap } = eventMappingParams;
@ -219,7 +221,7 @@ function useMultipleGuildSubscription<
>(
guild: CombinedGuild,
eventMappingParams: MultipleEventMappingParams<T, NE, UE, RE, CE>,
fetchFunc: () => Promise<T[]>
fetchFunc: () => Promise<T[] | null>
): [
fetchRetryCallable: () => Promise<void>,
lastResult: SubscriptionResult<T[]> | null,
@ -337,7 +339,7 @@ function useMultipleGuildSubscriptionScrolling<
eventMappingParams: MultipleEventMappingParams<T, NE, UE, RE, CE>,
maxElements: number,
maxFetchElements: number,
fetchFunc: () => Promise<T[]>,
fetchFunc: () => Promise<T[] | null>,
fetchAboveFunc: ((reference: T) => Promise<T[] | null>),
fetchBelowFunc: ((reference: T) => Promise<T[] | null>),
): [
@ -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<Resource | null, 'update-resource', 'conflict-resource'>(guild, {
return useSingleGuildSubscription<Resource, 'update-resource', 'conflict-resource'>(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<Resource> | 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 ?? '<null>'}`, { 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<Member, 'new-members', 'update-members', 'remove-members', 'conflict-members'>(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<Member | null> | 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<SubscriptionResult<Member | null> | 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 ]);