修复定时器与动画回调清理不完整问题
This commit is contained in:
@@ -42,7 +42,11 @@ export default function BlindboxRoomPage() {
|
||||
const timersRef = useRef<ReturnType<typeof setTimeout>[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => { timersRef.current.forEach(clearTimeout); };
|
||||
const timers = timersRef.current;
|
||||
return () => {
|
||||
timers.forEach(clearTimeout);
|
||||
timers.length = 0;
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Hook: Room
|
||||
@@ -58,7 +62,6 @@ export default function BlindboxRoomPage() {
|
||||
input, setInput, submitting, suggestions, suggestionsLoading,
|
||||
suggestionsSource, poolCount, setPoolCount, myIdeas, drawnHistory,
|
||||
setDrawnHistory, submitFlash, error, setError, inputRef,
|
||||
boxControls: ideaBoxControls,
|
||||
fetchIdeas, fetchSuggestions, refreshSuggestions,
|
||||
handleSubmit, handleEditIdea, handleDeleteIdea,
|
||||
} = useBlindboxIdeas(room, profile);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useRef, useCallback } from "react";
|
||||
import { useState, useRef, useCallback, useEffect } from "react";
|
||||
import { useAnimation } from "framer-motion";
|
||||
import confetti from "canvas-confetti";
|
||||
import type { DrawnIdea } from "@/components/BlindboxDrawnHistory";
|
||||
@@ -23,8 +23,21 @@ export function useBlindboxDraw(
|
||||
const boxControls = useAnimation();
|
||||
const confettiAliveRef = useRef(false);
|
||||
const timersRef = useRef<ReturnType<typeof setTimeout>[]>([]);
|
||||
const animationFrameRef = useRef<number | null>(null);
|
||||
|
||||
const stopConfetti = useCallback(() => {
|
||||
confettiAliveRef.current = false;
|
||||
if (animationFrameRef.current !== null) {
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
animationFrameRef.current = null;
|
||||
}
|
||||
timersRef.current.forEach(clearTimeout);
|
||||
timersRef.current = [];
|
||||
if (typeof confetti.reset === "function") confetti.reset();
|
||||
}, []);
|
||||
|
||||
const fireConfetti = useCallback(() => {
|
||||
stopConfetti();
|
||||
const colors = ["#a855f7", "#6366f1", "#ec4899", "#f59e0b", "#10b981"];
|
||||
confetti({ particleCount: 100, spread: 120, origin: { y: 0.4 }, colors, startVelocity: 45, ticks: 250 });
|
||||
confettiAliveRef.current = true;
|
||||
@@ -33,10 +46,21 @@ export function useBlindboxDraw(
|
||||
if (Date.now() > end || !confettiAliveRef.current) return;
|
||||
confetti({ particleCount: 3, angle: 60, spread: 55, origin: { x: 0, y: 0.6 }, colors, startVelocity: 35, ticks: 150 });
|
||||
confetti({ particleCount: 3, angle: 120, spread: 55, origin: { x: 1, y: 0.6 }, colors, startVelocity: 35, ticks: 150 });
|
||||
requestAnimationFrame(frame);
|
||||
animationFrameRef.current = requestAnimationFrame(frame);
|
||||
};
|
||||
timersRef.current.push(setTimeout(frame, 200));
|
||||
}, []);
|
||||
timersRef.current.push(
|
||||
setTimeout(() => {
|
||||
animationFrameRef.current = requestAnimationFrame(frame);
|
||||
}, 200),
|
||||
);
|
||||
}, [stopConfetti]);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
stopConfetti();
|
||||
},
|
||||
[stopConfetti],
|
||||
);
|
||||
|
||||
const handleDraw = async () => {
|
||||
if (poolCount === 0 || !profile || !room) {
|
||||
@@ -78,10 +102,11 @@ export function useBlindboxDraw(
|
||||
};
|
||||
|
||||
const handleContinue = useCallback(() => {
|
||||
stopConfetti();
|
||||
setPhase("pool");
|
||||
setRevealedIdea(null);
|
||||
setShowShareCard(false);
|
||||
}, [setPhase]);
|
||||
}, [setPhase, stopConfetti]);
|
||||
|
||||
return {
|
||||
revealedIdea,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback, useRef } from "react";
|
||||
import { useState, useCallback, useEffect, useRef } from "react";
|
||||
import { useAnimation } from "framer-motion";
|
||||
import { useToast } from "@/hooks/useToast";
|
||||
import type { MyIdea } from "@/components/BlindboxMyIdeas";
|
||||
@@ -51,6 +51,14 @@ export function useBlindboxIdeas(room: RoomInfo | null, profile: UserProfile | n
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const timersRef = useRef<ReturnType<typeof setTimeout>[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const timers = timersRef.current;
|
||||
return () => {
|
||||
timers.forEach(clearTimeout);
|
||||
timers.length = 0;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const fetchIdeas = useCallback(async () => {
|
||||
if (!room || !profile) return;
|
||||
try {
|
||||
|
||||
@@ -37,7 +37,11 @@ export function useBlindboxRoom(code: string) {
|
||||
const timersRef = useRef<ReturnType<typeof setTimeout>[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => { timersRef.current.forEach(clearTimeout); };
|
||||
const timers = timersRef.current;
|
||||
return () => {
|
||||
timers.forEach(clearTimeout);
|
||||
timers.length = 0;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user