mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-10 10:33:11 +03:00
fix React 19 infinite re-render loop on live dashboard
The "Maximum update depth exceeded" error was caused by two issues:
1. useDeferredStreamMetadata returned a new `{}` default on every render
when SWR data was undefined, creating an unstable reference that
triggered the useEffect in useCameraLiveMode on every render cycle.
Fixed by using a stable module-level EMPTY_METADATA constant.
2. useResizeObserver's rest parameter `...refs` created a new array on
every render, causing its useEffect to re-run and re-observe elements
continuously. Fixed by stabilizing refs with useRef and only
reconnecting the observer when actual DOM elements change.
This commit is contained in:
parent
4e37035d87
commit
f66af071d6
@ -31,25 +31,24 @@ export function useResizeObserver(...refs: RefType[]) {
|
||||
[],
|
||||
);
|
||||
|
||||
// Resolve refs to actual DOM elements for use as stable effect dependencies.
|
||||
// Rest params create a new array each call, but the underlying elements are
|
||||
// stable DOM nodes, so spreading them into the dep array avoids re-running
|
||||
// the effect on every render.
|
||||
const elements = refs.map((ref) =>
|
||||
ref instanceof Window ? document.body : ref.current,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
refs.forEach((ref) => {
|
||||
if (ref instanceof Window) {
|
||||
resizeObserver.observe(document.body);
|
||||
} else if (ref.current) {
|
||||
resizeObserver.observe(ref.current);
|
||||
}
|
||||
elements.forEach((el) => {
|
||||
if (el) resizeObserver.observe(el);
|
||||
});
|
||||
|
||||
return () => {
|
||||
refs.forEach((ref) => {
|
||||
if (ref instanceof Window) {
|
||||
resizeObserver.unobserve(document.body);
|
||||
} else if (ref.current) {
|
||||
resizeObserver.unobserve(ref.current);
|
||||
}
|
||||
});
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, [refs, resizeObserver]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [...elements, resizeObserver]);
|
||||
|
||||
if (dimensions.length == refs.length) {
|
||||
return dimensions;
|
||||
|
||||
@ -5,6 +5,7 @@ import { LiveStreamMetadata } from "@/types/live";
|
||||
|
||||
const FETCH_TIMEOUT_MS = 10000;
|
||||
const DEFER_DELAY_MS = 2000;
|
||||
const EMPTY_METADATA: { [key: string]: LiveStreamMetadata } = {};
|
||||
|
||||
/**
|
||||
* Hook that fetches go2rtc stream metadata with deferred loading.
|
||||
@ -77,7 +78,7 @@ export default function useDeferredStreamMetadata(streamNames: string[]) {
|
||||
return metadata;
|
||||
}, []);
|
||||
|
||||
const { data: metadata = {} } = useSWR<{
|
||||
const { data: metadata = EMPTY_METADATA } = useSWR<{
|
||||
[key: string]: LiveStreamMetadata;
|
||||
}>(swrKey, fetcher, {
|
||||
revalidateOnFocus: false,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user