How do trigger a rerender based on a timer but only on a specific component in React

I have a component that renders relative time

import React, { useEffect, useRef, useReducer } from 'react'
import { Text, TextProps } from 'react-native';
import { formatDistanceToNow } from 'date-fns';
type MomentTextProps = Omit<TextProps, 'children'> & {
  date: Date | number;
  pollTimeMs?: number;
}
export function MomentText({
  date, 
  pollTimeMs = 60000,
  ...props}: MomentTextProps) : JSX.Element {
  const [ formatted, update ] = useReducer(
    () => formatDistanceToNow(Date.now())
  );
  const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
  useEffect(()=> {
    timeoutRef.current = setTimeout(update, pollTimeMs);
    return () => {
      clearTimeout(timeoutRef.current!);
    };
  });

  return <Text {...props}>{formatted}</Text>
}

Which works, but seems overkill that I am creating so many timeouts, I was wondering if there’s a way of doing this via a “React context” but only rerender this one specific child.

The way I am thinking of it (as I type this) is to have a subscribe/notify hook like this…

/**
 * This hook provides a simple subscription semantic to React components.
 */
export function useSubscription<T = unknown>(): SubscriptionManager<T> {
  const subscribersRef = useRef<((data: T) => void)[]>([]);
  function subscribe(fn: (data: T) => void) {
    subscribersRef.current.push(fn);
    return () => {
      subscribersRef.current = subscribersRef.current.filter(
        (subscription) => !Object.is(subscription, fn)
      );
    };
  }
  function notify(data: T) {
    subscribersRef.current.forEach((fn) => fn(data));
  }
  function useSubscribeEffect(fn: (data: T) => void) {
    useEffect(() => subscribe(fn), []);
  }
  return { subscribe, notify, useSubscribeEffect };
}

and have a useRef and useEffect that will call notify on the MomentText component.

Seems quite overkill but not really sure which is worse.

The first approach is easy to understand, but may be a performance hit

The second is a bit more complicated, but the usage is isolated since it’s just a context requirement and everything else can be handled by subscriptions within the component.