Saltar al contenido principal

React Native 0.75: Compatibilidad con valores porcentuales en diseño, estabilización de la Nueva Arquitectura, actualizaciones de plantillas e init, y más

· 17 min de lectura
Gabriel Donadel Dall'Agnol
Gabriel Donadel Dall'Agnol
Software Engineer @ Expo
Siddharth Kulkarni
Siddharth Kulkarni
Software Engineer @ Coinbase
Thibault Malbranche
Thibault Malbranche
Lead Mobile Engineer @ Brigad
Blake Friedman
Blake Friedman
Software Engineer @ Meta
Riccardo Cipolleschi
Riccardo Cipolleschi
Software Engineer @ Meta
Nicola Corti
Nicola Corti
Software Engineer @ Meta
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 →

¡Hoy nos complace anunciar el lanzamiento de React Native 0.75!

Esta versión incluye varias características, como Yoga 3.1 con soporte para valores %, correcciones de estabilización para la Nueva Arquitectura, y la recomendación de utilizar un Framework de React Native.

Lo más destacado

Cambios importantes

Lo más destacado

Mejoras de Yoga 3.1 y diseño

Desde que incluimos Yoga versión 3.0 en React Native 0.74, hemos seguido implementando mejoras y nuevas capacidades de diseño para tus aplicaciones. React Native 0.75 incluye Yoga 3.1 y puedes conocer las novedades en la publicación oficial de Yoga.

Una característica destacada y muy solicitada es el soporte para valores % en varios contextos, como gaps y translation.

información

Estas características están disponibles solo en la Nueva Arquitectura. Si deseas utilizarlas, considera migrar a ella.

Valores porcentuales en gaps

En la versión 0.75, las props gap, columnGap y rowGap descritas aquí ahora admiten cadenas con valores %.

Por ejemplo:

function App(): React.JSX.Element {
return (
<SafeAreaView
style={{
marginTop: 20,
alignItems: 'center',
flex: 1,
rowGap: '20%',
}}>
<View
style={{flex: 1, flexDirection: 'row', columnGap: '10%'}}>
<View
style={{
backgroundColor: 'purple',
width: 100,
height: 100,
}}
/>
<View
style={{
backgroundColor: 'blue',
width: 100,
height: 100,
}}
/>
<View
style={{
backgroundColor: 'green',
width: 100,
height: 100,
}}
/>
</View>
<View
style={{flex: 1, flexDirection: 'row', columnGap: '10%'}}>
<View
style={{
backgroundColor: 'lime',
width: 100,
height: 100,
}}
/>
<View
style={{
backgroundColor: 'yellow',
width: 100,
height: 100,
}}
/>
<View
style={{
backgroundColor: 'orange',
width: 100,
height: 100,
}}
/>
</View>
<View
style={{flex: 1, flexDirection: 'row', columnGap: '10%'}}>
<View
style={{
backgroundColor: 'red',
width: 100,
height: 100,
}}
/>
<View
style={{
backgroundColor: 'violet',
width: 100,
height: 100,
}}
/>
<View
style={{
backgroundColor: 'magenta',
width: 100,
height: 100,
}}
/>
</View>
</SafeAreaView>
);
}

Se representará de la siguiente manera:

AndroidiOS
Android GapsiOS Gaps

Valores porcentuales en transformaciones de traslación

La prop transform ahora también puede aceptar % como valores en las transformaciones translate.

Por ejemplo, el siguiente componente movería la coordenada X del cuadrado rojo un 100% de su ancho y la coordenada Y un 100% de su altura:

function Translated() {
return (
<SafeAreaView
style={{
marginTop: 20,
flex: 1,
rowGap: '20%',
}}>
<View
style={{
backgroundColor: 'red',
width: 100,
height: 100,
transform: [{translateY: '100%'}, {translateX: '100%'}],
}}
/>
</SafeAreaView>
);
}

Se representará de la siguiente manera:

AndroidiOS
Android TranslationiOS Translation

Estabilización de la Nueva Arquitectura

Desde nuestro anuncio de que la Nueva Arquitectura estaba en Beta en React Conf, hemos implementado varias correcciones de errores y mejoras en su estabilidad.

Nuestro objetivo es que la Nueva Arquitectura se considere estable en un futuro próximo. Por lo tanto, en los últimos meses nos hemos centrado en cerrar las brechas entre la Arquitectura Antigua y la Nueva Arquitectura. Algunos ejemplos de errores y características faltantes que corregimos son:

  • Corrección de adjustsFontSizeToFit en Android (#44075)

  • Corrección de textAlign que no funcionaba con vistas en línea en Android (#44146)

  • Corrección del desplazamiento de la línea base del texto en iOS (#44932)

Junto con el equipo de Expo, también trabajamos en agregar información sobre el soporte de la Nueva Arquitectura en el Directorio de React Native, para que sea inmediatamente claro si una biblioteca ya es compatible con la Nueva Arquitectura:

Directorio de React Native

También te invitamos a participar en la encuesta sobre la Nueva Arquitectura. Esta encuesta es clave para recopilar comentarios valiosos sobre los próximos pasos del despliegue de la Nueva Arquitectura.

También queremos compartir una publicación que publicamos en el Grupo de Trabajo de Nueva Arquitectura sobre Compatibilidad con UIManager en la Nueva Arquitectura. Esta publicación ofrece una visión general de la API UIManager en Android y cómo puede ayudar en la migración de aplicaciones y bibliotecas más avanzadas.

Esta versión también contiene una nueva API que ahora es la forma recomendada para acceder al jsi::Runtime.

Acceso a jsi::Runtime en TurboModules

En el pasado, nunca hubo una forma recomendada desde los módulos nativos para acceder al jsi::Runtime, y los usuarios solían buscar soluciones alternativas riesgosas. En 0.74, introdujimos APIs experimentales que brindan acceso seguro al jsi::Runtime, y nos complace anunciar su estabilidad para 0.75.

Examples on how to access the jsi::Runtime

On iOS, you can make your Turbo Native Module conform to the protocol RCTTurboModuleWithJSIBindings. You can now implement installJSIBindingsWithRuntime, which will give you thread-safe access to the runtime.

@interface RCTSampleTurbo Module () <RCTTurboModuleWithJSIBindings>
@end

#pragma mark - RCTTurboModuleWithJSIBindings
- (void)installJSIBindingsWithRuntime:(jsi::Runtime &)runtime {
runtime.global().setProperty(
runtime,
"myGlobalFunction",
jsi:: Function::createFromHost Function(...));
}

On Android, you can make your Turbo Native Module conform to the interface TurboModuleWithBindings. You can now implement the JNI method getBindingsInstaller, which will give you thread-safe access to the runtime in C++.

public class SampleTurboModule extends NativeSampleTurboModuleSpec implements TurboModuleWithJSIBindings

@Override
public native BindingsInstallerHolder getBindingsInstaller();
// C++
jni::local_ref<BindingsInstallerHolder::javaobject> SampleTurboModuleJSIBindings::getBindingsInstaller(jni::alias_ref<jni::object> jobj) {
return BindingsInstallerHolder::newObjectCxxArgs(
[](jsi::Runtime& runtime) {
runtime.global().setProperty(
runtime,
“myGlobalFunction”,
jsi::Function::createFromHostFunction(...));
}
);
}

If you’re on the UI thread and you need to access the runtime, we introduced a new API: CallInvoker. It consists of a single method, invokeAsync, that will jump onto the JS thread to safely execute some work using the JS runtime. These APIs are forward compatible.

On iOS, we’ve provided the protocol RCTCallInvokerModule. After conforming to this protocol, our infrastructure will decorate the module with access to the CallInvoker.

@interface RCTSampleTurboModule() <RCTCallInvokerModule>

[self.callInvoker callInvoker].invokeAsync([&](jsi::Runtime& runtime) {
// do stuff on JS thread
}

On Android, the CallInvoker is accessible through the ReactContext in a JNI wrapper called CallInvokerHolder, where you can then call invokeAsync after crossing the JNI boundary.

// Java
public abstract CallInvokerHolder getJSCallInvokerHolder();
// C++
jsCallInvokerHolder->cthis()->getCallInvoker()->invokeAsync([&](jsi::Runtime& rt) {
// do stuff on JS thread
});

Uso de Frameworks

Como compartimos en React Conf a principios de este año, la forma recomendada para crear aplicaciones React Native es ahora mediante un framework como Expo.

Puedes leer más sobre esta recomendación en nuestra publicación anterior: "Usa un framework para crear aplicaciones React Native".

Queremos preparar a los nuevos usuarios de React Native para el éxito. Creemos que usar un framework te hace lo más productivo posible y ofrece la mejor experiencia de desarrollo al crear nuevas aplicaciones.

Para reflejar estas recomendaciones, esta versión incluye los siguientes cambios:

  • Movimos la carpeta /template del paquete react-native a un repositorio separado: react-native-community/template.

  • Estaremos descontinuando el comando react-native init a partir del 31 de diciembre de 2024.

Si ya usas un framework como Expo, estos cambios no te afectarán. Podrás usar React Native 0.75 con Expo SDK 51 (puedes encontrar instrucciones en esta publicación dedicada de Expo).

Si no usas un framework o estás construyendo tu propio framework, veamos cómo te afectarán estos cambios.

Traslado de la plantilla a react-native-community/template

Históricamente, react-native incluía una carpeta /template dentro del paquete NPM que utilizaba la Community CLI para crear nuevos proyectos. Esto hacía que actualizar la plantilla fuera bastante lento, ya que necesitábamos un nuevo lanzamiento de React Native por cada cambio en la plantilla.

Con nuestra última recomendación de usar un marco de trabajo, consideramos que incluir una plantilla con opiniones definidas dentro de nuestro paquete NPM central no estaba alineado con nuestra visión.

Por lo tanto, decidimos trasladar la plantilla al paquete @react-native-community/template.

Esto facilitará que la comunidad mantenga y evolucione la plantilla, sin tener que depender de un lanzamiento de React Native por cada cambio. Además, acerca la plantilla a la Community CLI y facilitará que todos puedan inspeccionar y depender de la plantilla como un paquete separado.

Este cambio debería ser completamente transparente para los usuarios que crean nuevos proyectos usando la Community CLI. A partir de ahora, los nuevos problemas relacionados con la plantilla deben reportarse en el seguimiento de problemas de la plantilla. Todas las diversas herramientas que dependen de la plantilla, como el upgrade-helper, también se han actualizado en consecuencia y seguirán funcionando como siempre.

Desaprobación de react-native init

De manera similar a la plantilla, el comando react-native init también se adaptó para alinearse con la nueva recomendación.

Históricamente, react-native init era el comando predeterminado para crear nuevos proyectos de React Native. Sin embargo, en 2024, consideramos que este comando no ofrece la misma experiencia de incorporación que un marco de trabajo te ofrecería. Por eso ya no lo recomendamos; en su lugar, deberías usar un marco de trabajo como Expo.

Aún puedes usar react-native init para crear nuevos proyectos usando la Community CLI y la plantilla hoy, pero verás la siguiente advertencia:

Desaprobación de init

A partir del 31 de diciembre de 2024, el comando init ya no creará un proyecto. Tendrás que:

  • Usar un marco de trabajo como Expo, con su propio comando dedicado para crear un nuevo proyecto, como npx create-expo-app

  • Invocar la Community CLI directamente con npx @react-native-community/cli init

Ten en cuenta que react-native config y todos los demás comandos aparte de init seguirán funcionando como siempre.

información

Para ofrecer una experiencia de migración más fluida, el paquete react-native@0.75.0 aún depende de @react-native-community/cli, pero planeamos eliminar esta dependencia en un futuro cercano.

Mejoras de rendimiento en el auto-linking

Durante este trabajo de actualización del comando init, también dedicamos tiempo a reescribir la lógica de auto-linking para que sea más eficiente. Esto resulta en una velocidad de compilación más rápida tanto para Android como para iOS.

Con React Native 0.75, si estás usando Expo, el paso de auto-linking ahora podría ejecutarse ~6.5 veces más rápido en Android y ~1.5 veces más rápido en iOS. Puedes leer más sobre estas mejoras aquí.

Cambios importantes

Aunque esta próxima sección parece extensa, esperamos que los cambios importantes aquí afecten principalmente a un pequeño grupo de usuarios que están usando React Native de maneras más avanzadas.

Queremos presentarlos aquí en aras de la exhaustividad y como referencia.

Los Touchables en TypeScript ya no pueden usarse como tipos en expresiones genéricas

Los componentes TouchablesOpacity y TouchableHighlights se han convertido en componentes funcionales. Esto significa que ya no se pueden utilizar como value & type. Por lo tanto, por ejemplo, lo siguiente ya no es válido:

import {TouchableHighlight} from 'react-native';
const ref = useRef<TouchableHighlight>();
// ^^^ TS2749: TouchableHighlight refers to a value, but is being used as a type here.
// Did you mean typeof TouchableHighlight?

En su lugar, deberías usar el tipo incorporado de React React.ElementRef o, alternativamente, el tipo View:

import {TouchableHighlight} from 'react-native';
const ref1 =
useRef<React.ElementRef<typeof TouchableHighlight>>();
// or
const ref2 = useRef<View>();

Última versión compatible con minSdk 23 y minIOSVersion 13.4

Estos no son cambios importantes en 0.75 en sí, pero queremos compartir que React Native 0.75 será la última versión de React Native compatible con minSdk 23 (Android 6.0) y minIOSVersion 13.4.

A partir de React Native 0.76, la versión minSdk será 24 (Android 7.0) y la minIOSVersion será 15.1.

Puedes leer más al respecto en nuestro anuncio oficial para Android y para iOS.

Android: Se ha eliminado JSIModule

El com.facebook.react.bridge.JSIModule (fuente) era una API que introdujimos temporalmente para permitir que un módulo nativo accediera directamente a JSI en Android. Los accesos a esta API se marcaron como obsoletos en 0.74, y verificamos que no había un uso significativo de esta API en código abierto, por lo que la eliminamos en 0.75. Puedes usar Turbo Native Modules como alternativa.

Android: Menú emergente trasladado a paquete separado

En 0.74, trasladamos el PopUpMenu de Android a un paquete separado bajo el ámbito @react-native. En 0.75, estamos eliminando los métodos restantes que aún estaban en el núcleo:

  • UIManagerModule.showPopupMenu()

  • UIManagerModule.dismissPopupMenu()

Como alternativa, por favor usa el componente <PopupMenuAndroid />, que se encuentra en el paquete @react-native/popup-menu-android.

iOS: Finalización del trabajo de desaprobación de PushNotificationIOS

En 0.74, marcamos como obsoletas algunas API del módulo PushNotificationIOS.

En 0.75, hemos eliminado estas API para migrarnos de las representaciones heredadas de metadatos de notificaciones.

Las API que se han eliminado son:

  + (void)didReceiveLocalNotification:(UILocalNotification *)notification;
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;

En su lugar, usa didReceiveNotification:(UNNotification *)notification.

CLI de la comunidad: Eliminación de comandos ram-bundle y profile-hermes

Nos complace anunciar dos eliminaciones importantes provenientes de la CLI de la comunidad: los comandos ram-bundle y profile-hermes.

El comando ram-bundle se introdujo en React Native 0.59 para permitirte ejecutar tus paquetes cargándolos directamente en memoria. Esta funcionalidad ahora ha sido reemplazada por Hermes, nuestro motor JS predeterminado. No deberías usar el comando ram-bundle.

El comando profile-hermes era una herramienta para perfilar el rendimiento de CPU de tu código JavaScript. Utilizaba el antiguo formato .cpuprofile, que ya no es compatible en versiones recientes de Chrome. También estamos abandonando esta funcionalidad como comando independiente mientras trabajamos para elevar el estándar de calidad de nuestras herramientas de depuración. Ahora puedes acceder al perfilado de CPU desde el panel "Profiler" en el Nuevo depurador experimental (Nota: no está disponible al conectarse a Hermes desde Chrome).

Otros cambios importantes

General

  • Codegen

    • Cambio sutil en nombres de clases y estructuras generadas para TurboModules de C++ puro. Eliminamos el token Cxx de sus nombres
    • Los enums float ya no son compatibles debido a posibles errores de precisión
    • Se lanza error al pasar null en JS a argumentos no nullable en Native
  • Linting

    • La configuración de ESLint ya no ejecuta prettier durante el linting
  • C++

    • ScrollViewShadowNode ahora requiere un nuevo parámetro bool includeTransform en el constructor
    • Eliminadas executeAsynchronously y executeSynchronously_CAN_DEADLOCK de RuntimeExecutor
    • Renombrado JsErrorHandlingFunc a OnJsError en JsErrorHandler.h
    • Renombrado handleJsError a OnJsError en handleFatalError.h
    • Eliminado import no utilizado de ReactPrimitives.h
    • Métodos get de LongLivedObjectCollection y LongLivedObject ahora aceptan parámetro Runtime
    • Renombrado archivo utils/jsi.h a jsi-utils.h
  • TextInput

    • Eliminado callback obsoleto onTextInput
  • Pressability

    • Eliminados métodos onLongPressShouldCancelPress_DEPRECATED, onResponderTerminationRequest_DEPRECATED y onStartShouldSetResponder_DEPRECATED

Android

  • ReactViewBackgroundDrawable

    • Obsoleto en favor de CSSBackgroundDrawable. Esto también elimina algunas API de ReactViewBackgroundDrawable y ColorUtil
  • ReactContext

    • ReactContext y ReactApplicationContext ahora son abstractas. Usa BridgeReactContext y BridgelessReactContext en su lugar
    • Eliminado ReactContext.initializeWithInstance(). Usa BridgeReactInstance en su lugar
    • Eliminado BridgelessReactContext.getJavaScriptContextHolder(). Usa BridgelessCatalystInstance en su lugar
    • Eliminado ReactContext.getRuntimeExecutor(). Usa BridgelessCatalystInstance
  • Layout

    • Soporte para valores porcentuales en flex gaps. Esto cambia parámetros de métodos como setGap, setRowGap y setColumnGap de float a dynamic
    • Requiere supportsRTL en Android Manifest
  • Runtime

    • Eliminado ReactJsExceptionHandler de ReactHostImpl
    • La aplicación debe devolver core turbomodules cuando no se usa el template predeterminado
  • DevSupport

    • Cambiado DevSupportManagerFactory.create() para aceptar nuevo parámetro PausedInDebuggerOverlayManager
  • Measurement

    • Eliminado UIManagerModule.measureLayoutRelativeToParent()

iOS

  • Runtime

    • Eliminados [RCTHost getSurfacePresenter] y [RCTHost getModuleRegistry]
    • Eliminada clase EventPriority. Siempre se usa EventPriority::AsynchronousBatched por defecto. Si falla el build, elimina cualquier uso de EventPriority
  • Image

    • Eliminado RCTImageLoadingPerfInstrumentationEnabled no utilizado
  • Error Handling

    • Eliminado acceso a RCTRedBox mediante RCTBridge
  • CocoaPods

    • Se renombró BUILD_FROM_SOURCE a RCT_BUILD_HERMES_FROM_SOURCE
    • Se renombró React-Codegen a ReactCodegen para mejorar la compatibilidad con use_frameworks y Swift
  • TextInput

    • Se eliminó el callback obsoleto onTextInput

Agradecimientos

React Native 0.75 contiene más de 1491 commits de 165 colaboradores. ¡Gracias por todo su arduo trabajo!

Agradecemos a los autores adicionales que contribuyeron a documentar características en esta publicación:

Actualización a la versión 0.75

Usa el React Native Upgrade Helper para ver cambios de código entre versiones de React Native en proyectos existentes, además de la documentación de actualización.

Para crear un nuevo proyecto:

npx @react-native-community/cli@latest init MyProject --version latest

Si usas Expo, React Native 0.75 será compatible con Expo SDK 51 (las instrucciones para actualizar React Native dentro de tu proyecto de Expo a 0.75.0 están disponibles en esta publicación dedicada).

información

0.75 es ahora la última versión estable de React Native y 0.72.x pasa a no ser compatible. Para más información consulta la política de soporte de React Native. Nuestro objetivo es publicar una actualización final de fin de vida para 0.72 en un futuro próximo.