Convert popular/suggested Groups to use Entities
This commit is contained in:
parent
50dadeb1b8
commit
7be8218f0c
|
@ -1,3 +1,4 @@
|
|||
export enum Entities {
|
||||
GROUP_MEMBERSHIPS = 'GroupMemberships'
|
||||
GROUP_MEMBERSHIPS = 'GroupMemberships',
|
||||
POPULAR_GROUPS = 'PopularGroups'
|
||||
}
|
|
@ -31,6 +31,8 @@ interface UseEntitiesOpts<TEntity extends Entity> {
|
|||
* It is 1 minute by default, and can be set to `Infinity` to opt-out of automatic fetching.
|
||||
*/
|
||||
staleTime?: number
|
||||
/** A flag to potentially disable sending requests to the API. */
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
/** A hook for fetching and displaying API entities. */
|
||||
|
@ -51,8 +53,11 @@ function useEntities<TEntity extends Entity>(
|
|||
|
||||
const entities = useAppSelector(state => selectEntities<TEntity>(state, path));
|
||||
|
||||
const isEnabled = opts.enabled ?? true;
|
||||
const isFetching = useListState(path, 'fetching');
|
||||
const lastFetchedAt = useListState(path, 'lastFetchedAt');
|
||||
const isFetched = useListState(path, 'fetched');
|
||||
const isError = !!useListState(path, 'error');
|
||||
|
||||
const next = useListState(path, 'next');
|
||||
const prev = useListState(path, 'prev');
|
||||
|
@ -72,6 +77,7 @@ function useEntities<TEntity extends Entity>(
|
|||
next: getNextLink(response),
|
||||
prev: getPrevLink(response),
|
||||
fetching: false,
|
||||
fetched: true,
|
||||
error: null,
|
||||
lastFetchedAt: new Date(),
|
||||
}));
|
||||
|
@ -101,20 +107,22 @@ function useEntities<TEntity extends Entity>(
|
|||
const staleTime = opts.staleTime ?? 60000;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFetching && (!lastFetchedAt || lastFetchedAt.getTime() + staleTime <= Date.now())) {
|
||||
if (isEnabled && !isFetching && (!lastFetchedAt || lastFetchedAt.getTime() + staleTime <= Date.now())) {
|
||||
fetchEntities();
|
||||
}
|
||||
}, [endpoint]);
|
||||
}, [endpoint, isEnabled]);
|
||||
|
||||
return {
|
||||
entities,
|
||||
fetchEntities,
|
||||
isFetching,
|
||||
isLoading: isFetching && entities.length === 0,
|
||||
hasNextPage: !!next,
|
||||
hasPreviousPage: !!prev,
|
||||
fetchNextPage,
|
||||
fetchPreviousPage,
|
||||
hasNextPage: !!next,
|
||||
hasPreviousPage: !!prev,
|
||||
isError,
|
||||
isFetched,
|
||||
isFetching,
|
||||
isLoading: isFetching && entities.length === 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ interface EntityListState {
|
|||
prev: string | undefined
|
||||
/** Error returned from the API, if any. */
|
||||
error: any
|
||||
/** Whether data has already been fetched */
|
||||
fetched: boolean
|
||||
/** Whether data for this list is currently being fetched. */
|
||||
fetching: boolean
|
||||
/** Date of the last API fetch for this list. */
|
||||
|
|
|
@ -29,8 +29,9 @@ const createList = (): EntityList => ({
|
|||
state: {
|
||||
next: undefined,
|
||||
prev: undefined,
|
||||
fetching: false,
|
||||
error: null,
|
||||
fetched: false,
|
||||
fetching: false,
|
||||
lastFetchedAt: undefined,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import { Carousel, Stack, Text } from 'soapbox/components/ui';
|
||||
import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
|
||||
import { usePopularGroups } from 'soapbox/queries/groups';
|
||||
import { usePopularGroups } from 'soapbox/hooks/api/usePopularGroups';
|
||||
|
||||
import GroupGridItem from './group-grid-item';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl';
|
|||
|
||||
import { Carousel, Stack, Text } from 'soapbox/components/ui';
|
||||
import PlaceholderGroupDiscover from 'soapbox/features/placeholder/components/placeholder-group-discover';
|
||||
import { useSuggestedGroups } from 'soapbox/queries/groups';
|
||||
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
||||
|
||||
import GroupGridItem from './group-grid-item';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import React from 'react';
|
|||
import { Widget } from 'soapbox/components/ui';
|
||||
import GroupListItem from 'soapbox/features/groups/components/discover/group-list-item';
|
||||
import PlaceholderGroupSearch from 'soapbox/features/placeholder/components/placeholder-group-search';
|
||||
import { useSuggestedGroups } from 'soapbox/queries/groups';
|
||||
import { useSuggestedGroups } from 'soapbox/hooks/api/useSuggestedGroups';
|
||||
|
||||
const SuggestedGroupsPanel = () => {
|
||||
const { groups, isFetching, isFetched, isError } = useSuggestedGroups();
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import { Entities } from 'soapbox/entity-store/entities';
|
||||
import { useEntities } from 'soapbox/entity-store/hooks';
|
||||
import { Group, groupSchema } from 'soapbox/schemas';
|
||||
|
||||
import { useFeatures } from '../useFeatures';
|
||||
import { useGroupRelationships } from '../useGroups';
|
||||
|
||||
function usePopularGroups() {
|
||||
const features = useFeatures();
|
||||
|
||||
const { entities, ...result } = useEntities<Group>(
|
||||
[Entities.POPULAR_GROUPS, ''],
|
||||
'/api/mock/groups', // '/api/v1/truth/trends/groups'
|
||||
{
|
||||
parser: parseGroup,
|
||||
enabled: features.groupsDiscovery,
|
||||
},
|
||||
);
|
||||
|
||||
const { relationships } = useGroupRelationships(entities.map(entity => entity.id));
|
||||
|
||||
const groups = entities.map((group) => ({
|
||||
...group,
|
||||
relationship: relationships[group.id] || null,
|
||||
}));
|
||||
|
||||
return {
|
||||
...result,
|
||||
groups,
|
||||
};
|
||||
}
|
||||
|
||||
const parseGroup = (entity: unknown) => {
|
||||
const result = groupSchema.safeParse(entity);
|
||||
if (result.success) {
|
||||
return result.data;
|
||||
}
|
||||
};
|
||||
|
||||
export { usePopularGroups };
|
|
@ -0,0 +1,40 @@
|
|||
import { Entities } from 'soapbox/entity-store/entities';
|
||||
import { useEntities } from 'soapbox/entity-store/hooks';
|
||||
import { Group, groupSchema } from 'soapbox/schemas';
|
||||
|
||||
import { useFeatures } from '../useFeatures';
|
||||
import { useGroupRelationships } from '../useGroups';
|
||||
|
||||
function useSuggestedGroups() {
|
||||
const features = useFeatures();
|
||||
|
||||
const { entities, ...result } = useEntities<Group>(
|
||||
[Entities.POPULAR_GROUPS, ''],
|
||||
'/api/mock/groups', // '/api/v1/truth/suggestions/groups'
|
||||
{
|
||||
parser: parseGroup,
|
||||
enabled: features.groupsDiscovery,
|
||||
},
|
||||
);
|
||||
|
||||
const { relationships } = useGroupRelationships(entities.map(entity => entity.id));
|
||||
|
||||
const groups = entities.map((group) => ({
|
||||
...group,
|
||||
relationship: relationships[group.id] || null,
|
||||
}));
|
||||
|
||||
return {
|
||||
...result,
|
||||
groups,
|
||||
};
|
||||
}
|
||||
|
||||
const parseGroup = (entity: unknown) => {
|
||||
const result = groupSchema.safeParse(entity);
|
||||
if (result.success) {
|
||||
return result.data;
|
||||
}
|
||||
};
|
||||
|
||||
export { useSuggestedGroups };
|
|
@ -44,4 +44,4 @@ function useGroupRelationships(groupIds: string[]) {
|
|||
};
|
||||
}
|
||||
|
||||
export { useGroup, useGroups };
|
||||
export { useGroup, useGroups, useGroupRelationships };
|
||||
|
|
|
@ -149,48 +149,6 @@ const usePendingGroups = () => {
|
|||
};
|
||||
};
|
||||
|
||||
const usePopularGroups = () => {
|
||||
const features = useFeatures();
|
||||
const { fetchGroups } = useGroupsApi();
|
||||
|
||||
const getQuery = async () => {
|
||||
const { groups } = await fetchGroups('/api/v1/truth/trends/groups');
|
||||
|
||||
return groups;
|
||||
};
|
||||
|
||||
const queryInfo = useQuery<Group[]>(GroupKeys.popularGroups, getQuery, {
|
||||
enabled: features.groupsDiscovery,
|
||||
placeholderData: [],
|
||||
});
|
||||
|
||||
return {
|
||||
groups: queryInfo.data || [],
|
||||
...queryInfo,
|
||||
};
|
||||
};
|
||||
|
||||
const useSuggestedGroups = () => {
|
||||
const features = useFeatures();
|
||||
const { fetchGroups } = useGroupsApi();
|
||||
|
||||
const getQuery = async () => {
|
||||
const { groups } = await fetchGroups('/api/v1/truth/suggestions/groups');
|
||||
|
||||
return groups;
|
||||
};
|
||||
|
||||
const queryInfo = useQuery<Group[]>(GroupKeys.suggestedGroups, getQuery, {
|
||||
enabled: features.groupsDiscovery,
|
||||
placeholderData: [],
|
||||
});
|
||||
|
||||
return {
|
||||
groups: queryInfo.data || [],
|
||||
...queryInfo,
|
||||
};
|
||||
};
|
||||
|
||||
const useGroup = (id: string) => {
|
||||
const features = useFeatures();
|
||||
const { fetchGroups } = useGroupsApi();
|
||||
|
@ -256,6 +214,4 @@ export {
|
|||
useJoinGroup,
|
||||
useLeaveGroup,
|
||||
usePendingGroups,
|
||||
usePopularGroups,
|
||||
useSuggestedGroups,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue