1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-05-05 01:27:46 +07:00

removed lab reducer

This commit is contained in:
Fedor Katurov 2022-01-05 15:57:29 +07:00
parent e24ea4afeb
commit 2b7b756212
26 changed files with 242 additions and 369 deletions

View file

@ -0,0 +1,85 @@
import useSWRInfinite from 'swr/infinite';
import { KeyLoader } from 'swr';
import { GetLabNodesRequest, ILabNode } from '~/types/lab';
import { getLabNodes } from '~/api/lab';
import { flatten, last, uniqBy } from 'ramda';
import { useLabStore } from '~/store/lab/useLabStore';
import { useCallback, useEffect } from 'react';
import { INode } from '~/redux/types';
import { useUser } from '~/hooks/user/userUser';
const getKey: (isUser: boolean) => KeyLoader<ILabNode[]> = isUser => (index, prev) => {
if (!isUser) return null;
if (index > 0 && !prev?.length) return null;
const lastNode = last(prev || []);
if (!lastNode && index > 0) {
return null;
}
const props: GetLabNodesRequest = {
after: lastNode?.node.commented_at || lastNode?.node.created_at,
};
return JSON.stringify(props);
};
const parseKey = (key: string): GetLabNodesRequest => {
try {
return JSON.parse(key);
} catch (error) {
return {};
}
};
export const useGetLabNodes = () => {
const labStore = useLabStore();
const { is_user } = useUser();
const { data, isValidating, size, setSize, mutate } = useSWRInfinite(
getKey(is_user),
async (key: string) => {
const result = await getLabNodes(parseKey(key));
return result.nodes;
},
{
fallbackData: [labStore.nodes],
onSuccess: data => labStore.setNodes(flatten(data)),
}
);
const nodes = uniqBy(n => n.node.id, flatten(data || []));
const hasMore = (data?.[size - 1]?.length || 0) >= 1;
const loadMore = useCallback(() => setSize(size + 1), [setSize, size]);
/** prepends list with a node */
const unshift = useCallback(
async (node: ILabNode) => {
await mutate([[node], ...(data || [])]);
},
[data, mutate]
);
/** updates node on cache */
const updateNode = useCallback(
async (nodeId: number, node: Partial<INode>) => {
await mutate(
data?.map(page =>
page.map(it => (it.node.id === nodeId ? { ...it, node: { ...it.node, node } } : it))
)
);
},
[data, mutate]
);
/** purge cache on exit */
useEffect(() => {
if (is_user) {
return;
}
labStore.setNodes([]);
}, [is_user, labStore]);
return { nodes, isLoading: !data && isValidating, hasMore, loadMore, unshift, updateNode };
};

View file

@ -0,0 +1,72 @@
import useSWR from 'swr';
import { API } from '~/constants/api';
import { getLabStats, getLabUpdates } from '~/api/lab';
import { useLabStore } from '~/store/lab/useLabStore';
import { useCallback, useEffect } from 'react';
import { useUser } from '~/hooks/user/userUser';
const refreshInterval = 1000 * 60 * 5; // 5 minutes
export const useGetLabStats = () => {
const lab = useLabStore();
const { is_user } = useUser();
const { data: stats, isValidating: isValidatingStats } = useSWR(
is_user ? API.LAB.STATS : null,
async () => getLabStats(),
{
fallbackData: {
heroes: lab.heroes,
tags: lab.tags,
},
onSuccess: data => {
lab.setHeroes(data.heroes);
lab.setTags(data.tags);
},
refreshInterval,
}
);
const { data: updatesData, isValidating: isValidatingUpdates, mutate: mutateUpdates } = useSWR(
is_user ? API.LAB.UPDATES : null,
async () => {
const result = await getLabUpdates();
return result.nodes;
},
{
fallbackData: lab.updates,
onSuccess: data => {
lab.setUpdates(data);
},
refreshInterval,
}
);
const heroes = stats?.heroes || [];
const tags = stats?.tags || [];
const updates = updatesData || [];
const isLoading = (!stats || !updates) && (isValidatingStats || isValidatingUpdates);
const seenNode = useCallback(
async (nodeId: number) => {
await mutateUpdates(
updates.filter(it => it.id !== nodeId),
false
);
},
[mutateUpdates, updates]
);
/** purge cache on exit */
useEffect(() => {
if (is_user) {
return;
}
lab.setHeroes([]);
lab.setTags([]);
lab.setUpdates([]);
}, [is_user, lab]);
return { heroes, tags, updates, isLoading, seenNode };
};

View file

@ -1,35 +1,9 @@
import { useShallowSelect } from '~/hooks/data/useShallowSelect';
import {
selectLabList,
selectLabStatsHeroes,
selectLabStatsLoading,
selectLabStatsTags,
selectLabUpdatesNodes,
} from '~/redux/lab/selectors';
import { useDispatch } from 'react-redux';
import { useCallback, useEffect } from 'react';
import { labGetList, labGetMore, labGetStats } from '~/redux/lab/actions';
import { useGetLabNodes } from '~/hooks/lab/useGetLabNodes';
import { useGetLabStats } from '~/hooks/lab/useGetLabStats';
export const useLab = () => {
const { is_loading: isLoading, nodes, count } = useShallowSelect(selectLabList);
const dispatch = useDispatch();
const tags = useShallowSelect(selectLabStatsTags);
const heroes = useShallowSelect(selectLabStatsHeroes);
const isLoadingStats = useShallowSelect(selectLabStatsLoading);
const updates = useShallowSelect(selectLabUpdatesNodes);
const { nodes, isLoading, loadMore, hasMore } = useGetLabNodes();
const { tags, heroes, updates, isLoading: isLoadingStats } = useGetLabStats();
useEffect(() => {
dispatch(labGetList());
dispatch(labGetStats());
}, [dispatch]);
const onLoadMore = useCallback(() => {
if (nodes.length >= count) {
return;
}
dispatch(labGetMore());
}, [nodes, count, dispatch]);
return { isLoading, nodes, count, onLoadMore, tags, heroes, isLoadingStats, updates };
return { isLoading, nodes, hasMore, loadMore, tags, heroes, isLoadingStats, updates };
};

View file

@ -1,44 +0,0 @@
import { useCallback, useEffect, useMemo } from 'react';
export const useLabPagination = (
isLoading: boolean,
columns: Element[],
onLoadMore: () => void
) => {
const loadOnIntersection = useCallback<IntersectionObserverCallback>(
entries => {
const isVisible = entries.some(entry => entry.intersectionRatio > 0);
if (!isVisible) {
return;
}
onLoadMore();
},
[onLoadMore]
);
const observer = useMemo(
() =>
new IntersectionObserver(loadOnIntersection, {
threshold: [0],
}),
[loadOnIntersection]
);
useEffect(() => {
if (isLoading) {
return;
}
const lastItems = Array.from(columns)
.map(col => col.children.item(col.childNodes.length - 1))
.filter(el => el) as Element[];
lastItems.forEach(item => observer.observe(item));
return () => {
lastItems.forEach(item => observer.unobserve(item));
};
}, [observer, columns, isLoading]);
};