Saltar al contenido principal
Versión: 0.78

Manipulación Directa

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

A veces es necesario modificar directamente un componente sin usar estado/props para activar un re-renderizado de todo el subárbol. Por ejemplo, al usar React en el navegador, ocasionalmente necesitas modificar directamente un nodo DOM, y lo mismo aplica para vistas en aplicaciones móviles. setNativeProps es el equivalente en React Native a establecer propiedades directamente en un nodo DOM.

precaución

¡Usa setNativeProps cuando los re-renderizados frecuentes creen cuellos de botella de rendimiento!

La manipulación directa no será una herramienta que uses frecuentemente. Normalmente solo la emplearás para crear animaciones continuas y evitar la sobrecarga de renderizar la jerarquía de componentes y reconciliar múltiples vistas. setNativeProps es imperativo y almacena estado en la capa nativa (DOM, UIView, etc.), no dentro de tus componentes React, lo que dificulta razonar sobre tu código.

Antes de usarlo, intenta resolver tu problema con setState y shouldComponentUpdate.

setNativeProps con TouchableOpacity

TouchableOpacity usa internamente setNativeProps para actualizar la opacidad de su componente hijo:

tsx
const viewRef = useRef<View>();
const setOpacityTo = useCallback(value => {
// Redacted: animation related code
viewRef.current.setNativeProps({
opacity: value,
});
}, []);

Esto nos permite escribir el siguiente código sabiendo que el hijo actualizará su opacidad al ser presionado, sin que este tenga conocimiento de ello ni requiera cambios en su implementación:

tsx
<TouchableOpacity onPress={handlePress}>
<View>
<Text>Press me!</Text>
</View>
</TouchableOpacity>

Imaginemos que setNativeProps no estuviera disponible. Una forma de implementarlo sería almacenar el valor de opacidad en el estado y actualizarlo cada vez que se active onPress:

tsx
const [buttonOpacity, setButtonOpacity] = useState(1);
return (
<TouchableOpacity
onPressIn={() => setButtonOpacity(0.5)}
onPressOut={() => setButtonOpacity(1)}>
<View style={{opacity: buttonOpacity}}>
<Text>Press me!</Text>
</View>
</TouchableOpacity>
);

Esto es computacionalmente más costoso que el ejemplo original: React debe re-renderizar toda la jerarquía de componentes cada vez que cambia la opacidad, aunque otras propiedades de la vista y sus hijos no hayan cambiado. Normalmente esta sobrecarga no es preocupante, pero al realizar animaciones continuas o responder a gestos, optimizar juiciosamente tus componentes puede mejorar la fidelidad de las animaciones.

Si examinas la implementación de setNativeProps en NativeMethodsMixin, notarás que es un envoltorio alrededor de RCTUIManager.updateView: exactamente la misma llamada que resulta de un re-renderizado (consulta receiveComponent en ReactNativeBaseComponent).

Componentes compuestos y setNativeProps

Los componentes compuestos no están respaldados por una vista nativa, por lo que no puedes llamar a setNativeProps en ellos. Considera este ejemplo:

Al ejecutarlo, verás inmediatamente este error: Touchable child must either be native or forward setNativeProps to a native component. Esto ocurre porque MyButton no está directamente respaldado por una vista nativa cuya opacidad deba establecerse. Piensa en esto: si defines un componente con createReactClass, no esperarías poder establecerle una prop de estilo directamente; necesitarías pasar la prop a un hijo, a menos que estés envolviendo un componente nativo. Similarmente, debemos reenviar setNativeProps a un componente hijo nativo.

Reenviar setNativeProps a un hijo

Dado que el método setNativeProps existe en cualquier referencia a un componente View, basta con reenviar una ref de tu componente personalizado a uno de los componentes <View /> que renderiza. Esto significa que una llamada a setNativeProps en el componente personalizado tendrá el mismo efecto que si llamaras a setNativeProps directamente en el componente View envuelto.

¡Ahora puedes usar MyButton dentro de TouchableOpacity!

Habrás notado que pasamos todas las props al componente hijo usando {...props}. Esto se debe a que TouchableOpacity es en realidad un componente compuesto que, además de requerir setNativeProps en su hijo, también necesita que el hijo maneje eventos táctiles. Para ello, pasa varias props que redirigen a la funcionalidad del componente TouchableOpacity. En cambio, TouchableHighlight está respaldado por una vista nativa y solo requiere que implementemos setNativeProps.

Usar setNativeProps para editar el valor de TextInput

Otro caso de uso muy común de setNativeProps es editar el valor de TextInput. La prop controlled de TextInput a veces puede omitir caracteres cuando el bufferDelay es bajo y el usuario escribe muy rápido. Algunos desarrolladores prefieren omitir esta prop y usar setNativeProps para manipular directamente el valor de TextInput cuando es necesario. Por ejemplo, este código demuestra cómo editar el input al pulsar un botón:

Puedes usar el método clear para limpiar el TextInput, que borra el texto actual usando el mismo enfoque.

Evitar conflictos con la función de renderizado

Si actualizas una propiedad que también es gestionada por la función de renderizado, podrías encontrar errores impredecibles porque cada vez que el componente se vuelva a renderizar y esa propiedad cambie, cualquier valor establecido previamente con setNativeProps será ignorado y sobrescrito.

setNativeProps y shouldComponentUpdate

Al aplicar inteligentemente shouldComponentUpdate, puedes evitar la sobrecarga innecesaria de reconciliar subárboles de componentes inalterados, hasta el punto donde puede ser suficientemente eficiente usar setState en lugar de setNativeProps.

Otros métodos nativos

Los métodos descritos están disponibles en la mayoría de los componentes predeterminados de React Native. Sin embargo, ten en cuenta que no están disponibles en componentes compuestos que no estén respaldados directamente por una vista nativa. Esto generalmente incluye la mayoría de los componentes que defines en tu propia aplicación.

measure(callback)

Determina la ubicación en pantalla, ancho y alto en el viewport de una vista dada y devuelve los valores mediante un callback asíncrono. Si tiene éxito, el callback se llamará con estos argumentos:

  • x

  • y

  • width

  • height

  • pageX

  • pageY

Nota: estas mediciones no están disponibles hasta que se completa el renderizado en nativo. Si necesitas las medidas lo antes posible y no requieres pageX y pageY, considera usar la propiedad onLayout.

Además, el ancho y alto devueltos por measure() corresponden al tamaño del componente en el viewport. Si necesitas el tamaño real del componente, usa la propiedad onLayout.

measureInWindow(callback)

Determina la ubicación de una vista dada en la ventana y devuelve los valores mediante un callback asíncrono. Si la vista raíz de React está incrustada en otra vista nativa, esto te dará las coordenadas absolutas. Si tiene éxito, el callback se llamará con estos argumentos:

  • x

  • y

  • width

  • height

measureLayout(relativeToNativeComponentRef, onSuccess, onFail)

Similar a measure(), pero mide la vista relativa a un ancestro especificado mediante la referencia relativeToNativeComponentRef. Esto significa que las coordenadas devueltas son relativas al origen x, y de la vista ancestro.

nota

Este método también puede llamarse con un manejador relativeToNativeNode (en lugar de referencia), pero esta variante está obsoleta con la nueva arquitectura.

focus()

Solicita el foco para la entrada o vista especificada. El comportamiento exacto dependerá de la plataforma y del tipo de vista.

blur()

Remueve el foco de una entrada o vista. Esto es lo opuesto a focus().