optimize mini ranking to only update when they are visible
Some checks failed
Deploy / deploy (push) Failing after 2m21s
Some checks failed
Deploy / deploy (push) Failing after 2m21s
This commit is contained in:
parent
50d5c0e5bc
commit
f30a373120
@ -12,6 +12,8 @@ import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
|
|||||||
import Card from "@/components/card";
|
import Card from "@/components/card";
|
||||||
import PlayerBadges from "@/components/player/player-badges";
|
import PlayerBadges from "@/components/player/player-badges";
|
||||||
import { useIsMobile } from "@/hooks/use-is-mobile";
|
import { useIsMobile } from "@/hooks/use-is-mobile";
|
||||||
|
import { useIsVisible } from "@/hooks/use-is-visible";
|
||||||
|
import { useRef } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
initialPlayerData: ScoreSaberPlayer;
|
initialPlayerData: ScoreSaberPlayer;
|
||||||
@ -29,6 +31,8 @@ export default function PlayerData({
|
|||||||
page,
|
page,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
const miniRankingsRef = useRef<any>();
|
||||||
|
const isMiniRankingsVisible = useIsVisible(miniRankingsRef);
|
||||||
|
|
||||||
let player = initalPlayerData;
|
let player = initalPlayerData;
|
||||||
const { data, isLoading, isError } = useQuery({
|
const { data, isLoading, isError } = useQuery({
|
||||||
@ -60,9 +64,9 @@ export default function PlayerData({
|
|||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<aside className="w-[600px] hidden 2xl:flex flex-col gap-2">
|
<aside ref={miniRankingsRef} className="w-[600px] hidden 2xl:flex flex-col gap-2">
|
||||||
<Mini type="Global" player={player} />
|
<Mini shouldUpdate={isMiniRankingsVisible} type="Global" player={player} />
|
||||||
<Mini type="Country" player={player} />
|
<Mini shouldUpdate={isMiniRankingsVisible} type="Country" player={player} />
|
||||||
</aside>
|
</aside>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,8 +15,20 @@ import { PlayerRankingSkeleton } from "@/components/ranking/player-ranking-skele
|
|||||||
const PLAYER_NAME_MAX_LENGTH = 18;
|
const PLAYER_NAME_MAX_LENGTH = 18;
|
||||||
|
|
||||||
type MiniProps = {
|
type MiniProps = {
|
||||||
|
/**
|
||||||
|
* The type of ranking to display.
|
||||||
|
*/
|
||||||
type: "Global" | "Country";
|
type: "Global" | "Country";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player on this profile.
|
||||||
|
*/
|
||||||
player: ScoreSaberPlayer;
|
player: ScoreSaberPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the data should be updated
|
||||||
|
*/
|
||||||
|
shouldUpdate?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Variants = {
|
type Variants = {
|
||||||
@ -53,7 +65,11 @@ const miniVariants: Variants = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Mini({ type, player }: MiniProps) {
|
export default function Mini({ type, player, shouldUpdate }: MiniProps) {
|
||||||
|
if (shouldUpdate == undefined) {
|
||||||
|
// Default to true
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
const variant = miniVariants[type];
|
const variant = miniVariants[type];
|
||||||
const icon = variant.icon(player);
|
const icon = variant.icon(player);
|
||||||
|
|
||||||
@ -88,6 +104,7 @@ export default function Mini({ type, player }: MiniProps) {
|
|||||||
|
|
||||||
return players;
|
return players;
|
||||||
},
|
},
|
||||||
|
enabled: shouldUpdate,
|
||||||
});
|
});
|
||||||
|
|
||||||
let players = data; // So we can update it later
|
let players = data; // So we can update it later
|
||||||
|
24
src/hooks/use-is-visible.ts
Normal file
24
src/hooks/use-is-visible.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the element is visible
|
||||||
|
*
|
||||||
|
* @param ref the ref of the element
|
||||||
|
*/
|
||||||
|
export function useIsVisible(ref: any) {
|
||||||
|
const [isIntersecting, setIntersecting] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (ref.current == null) {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
const observer = new IntersectionObserver(([entry]) => setIntersecting(entry.isIntersecting));
|
||||||
|
|
||||||
|
observer.observe(ref.current);
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
};
|
||||||
|
}, [ref]);
|
||||||
|
|
||||||
|
return isIntersecting;
|
||||||
|
}
|
Reference in New Issue
Block a user