Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

305
Vistas
Reaccionar useCallback con parámetro

El uso del useCallback de React es esencialmente solo un envoltorio alrededor de useMemo especializado para funciones para evitar la creación constante de nuevas instancias de funciones dentro de los accesorios de los componentes. Mi pregunta surge cuando necesita pasar un argumento a la devolución de llamada creada a partir de la memorización.

Por ejemplo, una devolución de llamada creada así...

 const Button: React.FunctionComponent = props => { const onClick = React.useCallback(() => alert('Clicked!'), []) return <button onClick={onClick}>{props.children}</button> }

es un ejemplo simple de una devolución de llamada memorizada y no requiere que se le pasen valores externos para realizar su trabajo. Sin embargo, si quiero crear una devolución de llamada memorizada genérica para un tipo de función React.Dipatch<React.SetStateAction> , entonces necesitaría argumentos... por ejemplo:

 const Button: React.FunctionComponent = props => { const [loading, setLoading] = React.useState(false) const genericSetLoadingCb = React.useCallback((x: boolean) => () => setLoading(x), []) return <button onClick={genericSetLoadingCb(!loading)}>{props.children}</button> }

En mi cabeza, parece que es exactamente lo mismo que hacer lo siguiente...

 const Button: React.FunctionComponent = props => { const [loading, setLoading] = React.useState(false) return <button onClick={() => setLoading(!loading)}>{props.children}</button> }

lo que permitiría frustrar el propósito de memorizar la función porque aún estaría creando una nueva función en cada representación, ya que genericSetLoadingCb(false) también devolvería una nueva función en cada representación.

¿Es correcto este entendimiento, o el patrón descrito con argumentos todavía mantiene los beneficios de la memorización?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Motivación y Declaración del Problema

Consideremos la siguiente función de orden superior genericCb (similar a su genericSetLoadingCb ):

 const genericCb = React.useCallback( (param) => (e) => setState({ ...state, [param]: e.target.value }), [] );

genericCb puede ser útil en la siguiente situación donde Input es un componente memorizado creado usando React.memo :

 <Input value={state.firstName} onChange={genericCb('firstName')} />

Dado que Input es un componente memorizado, es posible que deseemos que la función generada por genericCb('firstName') siga siendo la misma en los renderizados (para que el componente memorizado no se vuelva a renderizar innecesariamente). A continuación veremos cómo conseguirlo.

Solución

Ahora, la forma en que construimos genericCb arriba es que nos aseguramos de que permanezca igual en todas las representaciones (debido al uso de useCallback ).

Sin embargo, cada vez que llame a genericCb para crear una nueva función como esta:

 genericCb("firstName")

La función devuelta seguirá siendo diferente en cada renderizado . Para garantizar también que la función devuelta se memorice para alguna entrada, también debe usar algún enfoque de memorización:

 import memoize from "fast-memoize"; .... const genericCb = React.useCallback( memoize((param) => (e) => setState({ ...state, [param]: e.target.value })), [] );

Ahora, si llama a genericCb("firstName") para generar una función, devolverá la misma función en cada procesamiento, siempre que "firstName" también siga siendo el mismo .

Observaciones

Como se señaló en los comentarios anteriores, la solución que usa useCallback parece generar una advertencia (aunque no en mi proyecto):

React Hook useCallback recibió una función cuyas dependencias se desconocen. Pase una función en línea en su lugar

Parece que la advertencia está ahí porque no pasamos la función en línea a useCallback . La solución que encontré para deshacerme de esta advertencia basada en este hilo de github es usar useMemo para imitar useCallback de esta manera:

 // Use this; this doesn't produce the warning anymore const genericCb = React.useMemo( () => memoize( (param) => (e) => setState({ ...state, [param]: e.target.value }) ), [] );

Simplemente usar memoize sin useCallback (o useMemo como en la actualización) no funcionaría, ya que en el siguiente render invocaría memoize desde nuevo como este:

 let memoized = memoize(fn) memoized('foo', 3, 'bar') memoized('foo', 3, 'bar') // cache hit memoized = memoize(fn); // without useCallback (or useMemo) this would happen on next render // Now the previous cache is lost
over 4 years ago · Santiago Trujillo Denunciar

0

Parece que hacer lo siguiente es una forma elegante y sencilla de resolver su problema. No creará una nueva función cb si Button solo se está volviendo a representar.

 const Button = props => { const [loading, setLoading] = React.useState(false) const cb = React.useCallback(() => { setLoading(!loading) }, [loading]); return <button onClick={cb}>{props.children}</button> }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda