diff --git a/apps/client/src/common/hooks-query/useRundown.ts b/apps/client/src/common/hooks-query/useRundown.ts index b1fc96dab..ecbb2fb99 100644 --- a/apps/client/src/common/hooks-query/useRundown.ts +++ b/apps/client/src/common/hooks-query/useRundown.ts @@ -65,6 +65,10 @@ export function useFlatRundownWithMetadata() { /** * Provides access to a partial rundown based on a filter callback + * + * Callers MUST memoize the callback with useCallback to prevent + * re-filtering on every render. + * */ export function usePartialRundown(cb: (event: ExtendedEntry) => boolean) { const { data, status } = useFlatRundownWithMetadata(); diff --git a/apps/client/src/views/common/schedule/ScheduleContext.tsx b/apps/client/src/views/common/schedule/ScheduleContext.tsx index 39f34023c..d2c9cc214 100644 --- a/apps/client/src/views/common/schedule/ScheduleContext.tsx +++ b/apps/client/src/views/common/schedule/ScheduleContext.tsx @@ -1,4 +1,14 @@ -import { createContext, PropsWithChildren, RefObject, use, useEffect, useLayoutEffect, useRef, useState } from 'react'; +import { + createContext, + PropsWithChildren, + RefObject, + use, + useCallback, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react'; import { EntryId, isOntimeEvent, OntimeEntry, OntimeEvent } from 'ontime-types'; import { usePartialRundown } from '../../../common/hooks-query/useRundown'; @@ -22,14 +32,20 @@ interface ScheduleProviderProps { export const ScheduleProvider = ({ children, selectedEventId }: PropsWithChildren) => { const { cycleInterval, stopCycle, filter } = useScheduleOptions(); - const { data: events } = usePartialRundown((entry: ExtendedEntry) => { - if (filter) { - // custom keys are prepended with custom- - const customKey = filter.startsWith('custom-') ? filter.slice('custom-'.length) : filter; - return isOntimeEvent(entry) && Boolean(entry.custom[customKey]); - } - return isOntimeEvent(entry); - }); + + const filterCallback = useCallback( + (entry: ExtendedEntry) => { + if (filter) { + // custom keys are prepended with custom- + const customKey = filter.startsWith('custom-') ? filter.slice('custom-'.length) : filter; + return isOntimeEvent(entry) && Boolean(entry.custom[customKey]); + } + return isOntimeEvent(entry); + }, + [filter], + ); + + const { data: events } = usePartialRundown(filterCallback); const [firstIndex, setFirstIndex] = useState(-1); const [numPages, setNumPages] = useState(0);