builds page show loading without layout jumps

This commit is contained in:
Kalle (Sendou)
2020-11-25 17:31:02 +02:00
parent a4915afb8a
commit 390a8af43d
3 changed files with 79 additions and 32 deletions

View File

@@ -0,0 +1,32 @@
import { Flex, Skeleton } from "@chakra-ui/react";
const BuildsSkeleton = () => (
<Flex flexWrap="wrap" justifyContent="center" mt={4}>
<Skeleton
w="300px"
height="500px"
rounded="lg"
boxShadow="md"
p="20px"
m={2}
/>
<Skeleton
w="300px"
height="500px"
rounded="lg"
boxShadow="md"
p="20px"
m={2}
/>
<Skeleton
w="300px"
height="500px"
rounded="lg"
boxShadow="md"
p="20px"
m={2}
/>
</Flex>
);
export default BuildsSkeleton;

View File

@@ -110,15 +110,17 @@ export function useBuildsByWeapon() {
{ weapon: "", filters: [], expandedUsers: new Set() as Set<number> }
);
const { data = [] } = useSWR<GetBuildsByWeaponData>(() => {
const { data } = useSWR<GetBuildsByWeaponData>(() => {
if (!state.weapon) return null;
const key = state.weapon as keyof typeof weaponToCode;
return `/api/builds/${weaponToCode[key]}`;
});
const buildArrays = data ?? [];
const buildsToShow = state.filters.length
? data.reduce((acc: GetBuildsByWeaponData, buildArray) => {
? buildArrays.reduce((acc: GetBuildsByWeaponData, buildArray) => {
const filteredArray = buildArray.filter((build) => {
return state.filters.every((filter) => {
// @ts-ignore
@@ -146,12 +148,13 @@ export function useBuildsByWeapon() {
return [...acc, filteredArray];
}, [])
: data;
: buildArrays;
return {
data: buildsToShow,
isLoading: state.weapon && !data,
state,
dispatch,
hiddenBuildCount: data.length - buildsToShow.length,
hiddenBuildCount: buildArrays.length - buildsToShow.length,
};
}

View File

@@ -2,6 +2,7 @@ import { Box, Flex } from "@chakra-ui/react";
import { t, Trans } from "@lingui/macro";
import BuildCard from "components/builds/BuildCard";
import BuildFilters from "components/builds/BuildFilters";
import BuildsSkeleton from "components/builds/BuildsSkeleton";
import Breadcrumbs from "components/common/Breadcrumbs";
import MyInfiniteScroller from "components/common/MyInfiniteScroller";
import WeaponImage from "components/common/WeaponImage";
@@ -10,7 +11,13 @@ import { useBuildsByWeapon } from "hooks/builds";
import { useMyTheme } from "lib/useMyTheme";
const BuildsPage = () => {
const { data, state, dispatch, hiddenBuildCount } = useBuildsByWeapon();
const {
data,
isLoading,
state,
dispatch,
hiddenBuildCount,
} = useBuildsByWeapon();
const { themeColorHex } = useMyTheme();
return (
<>
@@ -21,39 +28,44 @@ const BuildsPage = () => {
excludeAlt
isHeader
/>
{state.weapon && (data.length > 0 || hiddenBuildCount > 0) && (
<>
<Box mt={4} pr={3} mb="-5rem">
<>
<Box mt={4} pr={3} mb="-5rem">
{state.weapon ? (
<WeaponImage name={state.weapon} size={128} />
</Box>
<Flex
justifyContent="flex-end"
p={2}
mb={8}
w="100%"
bg={`linear-gradient(to right, ${themeColorHex}, #f8ffae);`}
rounded="lg"
fontSize="sm"
boxShadow="md"
color="black"
>
<Flex justifyContent="space-between">
<Box>
{data.length} <Trans>builds</Trans>{" "}
{hiddenBuildCount > 0 && (
<>
(+ {hiddenBuildCount} <Trans>hidden</Trans>)
</>
)}
</Box>
</Flex>
) : (
<Box w="135px" h="135px" />
)}
</Box>
<Flex
justifyContent="flex-end"
p={2}
mb={8}
w="100%"
bg={themeColorHex}
rounded="lg"
fontSize="sm"
boxShadow="md"
color="black"
>
<Flex justifyContent="space-between">
<Box visibility={data.length === 0 ? "hidden" : undefined}>
{data.length} <Trans>builds</Trans>{" "}
{hiddenBuildCount > 0 && (
<>
(+ {hiddenBuildCount} <Trans>hidden</Trans>)
</>
)}
</Box>
</Flex>
</>
)}
</Flex>
</>
{state.weapon && (
<BuildFilters filters={state.filters} dispatch={dispatch} />
)}
{isLoading && <BuildsSkeleton />}
<MyInfiniteScroller>
{data.flatMap((buildArray) =>
state.expandedUsers.has(buildArray[0].userId) ? (