Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

233
Views
¿Cómo desencadenar un renderizado basado en un temporizador pero solo en un componente específico en React?

Tengo un componente que representa el tiempo relativo

 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()), formatDistanceToNow(Date.now()) ); const timeoutRef = useRef<ReturnType<typeof setTimeout>>(); function doUpdate() { update(); timeoutRef.current = setTimeout(update, pollTimeMs); } useEffect(() => { doUpdate(); return () => { clearTimeout(timeoutRef.current!); }; }); return <Text {...props}>{formatted}</Text> }

Lo cual funciona, pero parece exagerado que esté creando tantos tiempos de espera, me preguntaba si hay una manera de hacer esto a través de un "contexto de reacción" pero solo volver a renderizar este niño específico.

La forma en que lo pienso (mientras escribo esto) es tener un gancho de subscribe/notify como este...

 /** * 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 }; }

y tenga un useRef y useEffect que llamará a notify en el componente MomentText .

Parece bastante exagerado, pero no estoy seguro de qué es peor.

El primer enfoque es fácil de entender, pero puede ser un golpe de rendimiento

El segundo es un poco más complicado, pero el uso está aislado ya que es solo un requisito de contexto y todo lo demás puede ser manejado por suscripciones dentro del componente.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Parece que la idea que tuve con el contexto funcionaría, pero tuve que crear un nuevo enlace llamado useClock que se implementa a continuación.

 import { useEffect, useRef } from "react"; import { SubscriptionManager, useSubscription } from "../useSubscription"; /** * time to next full minute from the date * @param date * @returns milliseconds to next full minute from date */ function timeToNextFullMinute(date: number): number { return 60000 - (date % 60000); } /** * This hook notifies the subscribers with the current date. This * is useful for updating components that show moment in time without * a full rerender of the tree. * * It notifies at the following points: * - useEffect * - first minute at zero seconds * - every minute after at zero seconds * * However, due to the performance of the device, this may not be acurate. * * @returns subscription manager */ export function useClock(): SubscriptionManager<number> { const { subscribe, notify, useSubscribeEffect } = useSubscription<number>(); const timeoutRef = useRef<ReturnType<typeof setTimeout>>(); function doNotify() { notify(Date.now()); timeoutRef.current = setTimeout(doNotify, timeToNextFullMinute(Date.now())); } useEffect(() => { doNotify(); return () => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion clearTimeout(timeoutRef.current!); }; }, []); return { subscribe, notify, useSubscribeEffect }; }

Mi contexto luego proporcionaría el useSubscribeEffect específico para el useClock que luego uso de MomentText , que sería:

 type MomentTextProps = Omit<TextProps, "children"> & { on: Date | number; }; export function MomentText({ on, ...props }: MomentTextProps): JSX.Element { const { useClockSubscribeEffect } = useDevhausUI(); const { formatRelativeToNow } = useLocalization(); const [text, setText] = useState(formatRelativeToNow(on)); useClockSubscribeEffect(() => setText(formatRelativeToNow(on))); return <Text {...props}>{text}</Text>; }

Con este enfoque, el tiempo de espera se administra en el useClock() y es parte de un contexto, por lo que no hay demasiados corriendo.

Fuente y prueba disponibles en https://github.com/trajano/react-hooks-tests/tree/master/src/useClock

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!