mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-05 14:47:40 +03:00
fix: prevent infinite render loop in zoom overlay callbacks
Use useRef to store onStatsUpdate/onLoadingChange/onActiveMotionChange callbacks so useEffect deps don't include the callback references. Inline arrow functions in .map() change identity every render, causing the previous useEffect([stats, onCallback]) to re-fire on each parent re-render, triggering another setState → re-render → infinite loop. https://claude.ai/code/session_019B4dJXtcxvHn97ZaqHUB62
This commit is contained in:
parent
9307272007
commit
89864e364d
@ -111,9 +111,16 @@ export default function LivePlayer({
|
|||||||
droppedFrameRate: 0, // percentage
|
droppedFrameRate: 0, // percentage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const onStatsUpdateRef = useRef(onStatsUpdate);
|
||||||
|
const onLoadingChangeRef = useRef(onLoadingChange);
|
||||||
|
const onActiveMotionChangeRef = useRef(onActiveMotionChange);
|
||||||
|
onStatsUpdateRef.current = onStatsUpdate;
|
||||||
|
onLoadingChangeRef.current = onLoadingChange;
|
||||||
|
onActiveMotionChangeRef.current = onActiveMotionChange;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onStatsUpdate?.(stats);
|
onStatsUpdateRef.current?.(stats);
|
||||||
}, [stats, onStatsUpdate]);
|
}, [stats]);
|
||||||
|
|
||||||
// camera activity
|
// camera activity
|
||||||
|
|
||||||
@ -285,40 +292,24 @@ export default function LivePlayer({
|
|||||||
}, [liveReady, isReEnabling]);
|
}, [liveReady, isReEnabling]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!onLoadingChange) return;
|
|
||||||
const loading = !!(
|
const loading = !!(
|
||||||
cameraEnabled &&
|
cameraEnabled &&
|
||||||
!offline &&
|
!offline &&
|
||||||
(!showStillWithoutActivity || isReEnabling) &&
|
(!showStillWithoutActivity || isReEnabling) &&
|
||||||
!liveReady
|
!liveReady
|
||||||
);
|
);
|
||||||
onLoadingChange(loading);
|
onLoadingChangeRef.current?.(loading);
|
||||||
}, [
|
}, [cameraEnabled, offline, showStillWithoutActivity, isReEnabling, liveReady]);
|
||||||
onLoadingChange,
|
|
||||||
cameraEnabled,
|
|
||||||
offline,
|
|
||||||
showStillWithoutActivity,
|
|
||||||
isReEnabling,
|
|
||||||
liveReady,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!onActiveMotionChange) return;
|
|
||||||
const motionVisible = !!(
|
const motionVisible = !!(
|
||||||
autoLive &&
|
autoLive &&
|
||||||
!offline &&
|
!offline &&
|
||||||
activeMotion &&
|
activeMotion &&
|
||||||
((showStillWithoutActivity && !liveReady) || liveReady)
|
((showStillWithoutActivity && !liveReady) || liveReady)
|
||||||
);
|
);
|
||||||
onActiveMotionChange(motionVisible);
|
onActiveMotionChangeRef.current?.(motionVisible);
|
||||||
}, [
|
}, [autoLive, offline, activeMotion, showStillWithoutActivity, liveReady]);
|
||||||
onActiveMotionChange,
|
|
||||||
autoLive,
|
|
||||||
offline,
|
|
||||||
activeMotion,
|
|
||||||
showStillWithoutActivity,
|
|
||||||
liveReady,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!cameraConfig) {
|
if (!cameraConfig) {
|
||||||
return <ActivityIndicator />;
|
return <ActivityIndicator />;
|
||||||
@ -453,7 +444,7 @@ export default function LivePlayer({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!onLoadingChange &&
|
{!onLoadingChangeRef.current &&
|
||||||
cameraEnabled &&
|
cameraEnabled &&
|
||||||
!offline &&
|
!offline &&
|
||||||
(!showStillWithoutActivity || isReEnabling) &&
|
(!showStillWithoutActivity || isReEnabling) &&
|
||||||
@ -577,7 +568,7 @@ export default function LivePlayer({
|
|||||||
{cameraName}
|
{cameraName}
|
||||||
</Chip>
|
</Chip>
|
||||||
)}
|
)}
|
||||||
{!onActiveMotionChange &&
|
{!onActiveMotionChangeRef.current &&
|
||||||
autoLive &&
|
autoLive &&
|
||||||
!offline &&
|
!offline &&
|
||||||
activeMotion &&
|
activeMotion &&
|
||||||
@ -585,7 +576,7 @@ export default function LivePlayer({
|
|||||||
<MdCircle className="mr-2 size-2 animate-pulse text-danger shadow-danger drop-shadow-md" />
|
<MdCircle className="mr-2 size-2 animate-pulse text-danger shadow-danger drop-shadow-md" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showStats && !onStatsUpdate && (
|
{showStats && !onStatsUpdateRef.current && (
|
||||||
<PlayerStats stats={stats} minimal={cameraRef !== undefined} />
|
<PlayerStats stats={stats} minimal={cameraRef !== undefined} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user