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 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
|
||||
|
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