optimize mini ranking to only update when they are visible
Some checks failed
Deploy / deploy (push) Failing after 2m21s

This commit is contained in:
Lee 2024-10-01 14:46:44 +01:00
parent 50d5c0e5bc
commit f30a373120
3 changed files with 49 additions and 4 deletions

@ -12,6 +12,8 @@ import ScoreSaberPlayer from "@/common/model/player/impl/scoresaber-player";
import Card from "@/components/card";
import PlayerBadges from "@/components/player/player-badges";
import { useIsMobile } from "@/hooks/use-is-mobile";
import { useIsVisible } from "@/hooks/use-is-visible";
import { useRef } from "react";
type Props = {
initialPlayerData: ScoreSaberPlayer;
@ -29,6 +31,8 @@ export default function PlayerData({
page,
}: Props) {
const isMobile = useIsMobile();
const miniRankingsRef = useRef<any>();
const isMiniRankingsVisible = useIsVisible(miniRankingsRef);
let player = initalPlayerData;
const { data, isLoading, isError } = useQuery({
@ -60,9 +64,9 @@ export default function PlayerData({
/>
</article>
{!isMobile && (
<aside className="w-[600px] hidden 2xl:flex flex-col gap-2">
<Mini type="Global" player={player} />
<Mini type="Country" player={player} />
<aside ref={miniRankingsRef} className="w-[600px] hidden 2xl:flex flex-col gap-2">
<Mini shouldUpdate={isMiniRankingsVisible} type="Global" player={player} />
<Mini shouldUpdate={isMiniRankingsVisible} type="Country" player={player} />
</aside>
)}
</div>

@ -15,8 +15,20 @@ import { PlayerRankingSkeleton } from "@/components/ranking/player-ranking-skele
const PLAYER_NAME_MAX_LENGTH = 18;
type MiniProps = {
/**
* The type of ranking to display.
*/
type: "Global" | "Country";
/**
* The player on this profile.
*/
player: ScoreSaberPlayer;
/**
* Whether the data should be updated
*/
shouldUpdate?: boolean;
};
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 icon = variant.icon(player);
@ -88,6 +104,7 @@ export default function Mini({ type, player }: MiniProps) {
return players;
},
enabled: shouldUpdate,
});
let players = data; // So we can update it later

@ -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;
}