Przejdź do treści głównej

React Native 0.74 - Yoga 3.0, Bridgeless New Architecture i więcej

· 14 minut czytania
Hur Ali
Hur Ali
Software Engineer @ Callstack
Alan Hughes
Alan Hughes
Software Engineer @ Expo
Alfonso Curbelo
Alfonso Curbelo
Software Engineer @ Coinbase
Alex Hunt
Alex Hunt
Software Engineer @ Meta
Nicola Corti
Nicola Corti
Software Engineer @ Meta
Nieoficjalne Tłumaczenie Beta

Ta strona została przetłumaczona przez PageTurner AI (beta). Nie jest oficjalnie zatwierdzona przez projekt. Znalazłeś błąd? Zgłoś problem →

Dziś wydajemy React Native 0.74! Ta wersja wprowadza Yoga 3.0, domyślną opcję Bridgeless w ramach Nowej Architektury, zbiorcze aktualizacje onLayout (Nowa Architektura) oraz Yarn 3 jako domyślny menedżer pakietów dla nowych projektów.

Usuwamy również przestarzałe API, w tym usunięcie PropTypes oraz zmiany łamiące kompatybilność w PushNotificationIOS. W przypadku Androida, SDK 23 (Android 6.0) jest teraz minimalną obsługiwaną wersją.

Najważniejsze zmiany

Zmiany łamiące kompatybilność

Najważniejsze zmiany

Yoga 3.0

Nowe zachowania układu

React Native 0.74 zawiera Yoga 3.0, najnowszą wersję naszego silnika układu. Yoga 3.0 poprawia układ poprzez zwiększenie przewidywalności stylowania oraz obsługuje renderowanie komponentów napisanych dla webu.

React Native nadal celowo zachowuje niektóre niepoprawne zachowania układu, gdyż naprawienie ich wpłynęłoby znacząco na wiele istniejących komponentów. W przyszłych wersjach React Native będzie możliwe bardziej szczegółowe konfigurowanie zgodności układu.

ostrzeżenie

React Native wcześniej zamieniał miejscami krawędzie left/right (oraz start/end) przy ustawianiu margin, padding lub border w kontenerach z row-reverse. Teraz zachowanie tych właściwości jest zgodne z zachowaniem na stronach internetowych. Kod, który wcześniej polegał na odwróconych krawędziach, może wymagać aktualizacji, aby zachować poprawne renderowanie.

StyleBeforeAfter
<View
style={{
flexDirection: 'row',
backgroundColor: 'red',
margin: 10,
width: 200,
height: 100,
}}>
<View
style={{
flexDirection: 'row-reverse',
backgroundColor: 'blue',
flex: 1,
marginLeft: 50,
}}>
<View
style={{
backgroundColor: 'green',
height: '50%',
flex: 1,
marginLeft: 50,
}}
/>
</View>
</View>

Previous layout

New layout

Obsługa align-content: 'space-evenly'

Yoga 3.0 wprowadza obsługę alignContent: 'space-evenly'. space-evenly rozkłada linie w kontenerze flex z wieloma liniami, używając równomiernie rozmieszczonych odstępów między liniami oraz krawędziami kontenera.

Visual reference for alignContent behaviors
Source: World Wide Web Consortium

Obsługa position: 'static'

informacja

position: 'static' jest obsługiwane tylko w Nowej Architekturze.

Elementy oznaczone jako position: 'static' nie mogą być przesuwane i nie są brane pod uwagę przy określaniu kontenera blokowego dla elementów z pozycją absolutną. Pozwala to pozycjonować element względem przodka, który nie jest jego bezpośrednim rodzicem.

<View
style={{
backgroundColor: 'blue',
width: 200,
height: 200,
flexDirection: 'row-reverse',
}}>
<View
style={{
backgroundColor: 'red',
width: 100,
height: 100,
position: 'static',
}}>
<View
style={{
backgroundColor: 'green',
width: 25,
height: '25%',
left: 25,
top: 25,
position: 'absolute',
}}
/>
</View>
</View>

Static Example

Zwróć uwagę, jak zielony <View> deklaruje left i top, a pozycjonowany jest względem niebieskiego <View>, a nie swojego rodzica.

React Native nadal domyślnie używa position: 'relative', gdy nie ustawiono position.

Nowa Architektura: Bridgeless domyślnie

W tym wydaniu ustawiamy tryb Bridgeless jako domyślny, gdy włączona jest Nowa Architektura. Więcej o przejściu na Bridgeless jako domyślny tryb możesz przeczytać w tym poście. Aby ułatwić przejście, udoskonaliliśmy warstwy interoperacyjne dla Bridgeless i współpracowaliśmy z wieloma bibliotekami, aby zapewnić ich działanie w Bridgeless od pierwszego dnia.

Bridgeless to nie jedyna warstwa interoperacyjna, nad którą pracowaliśmy: udoskonaliliśmy także warstwy interoperacyjne Nowego Renderera. Najciekawsze jest to, że są teraz domyślnie włączone - nie musisz wskazywać komponentów, które mają przez nie przechodzić! Więcej informacji znajdziesz tutaj.

Jeśli chcesz dowiedzieć się więcej o Nowej Architekturze, dokumentację znajdziesz w repozytorium react-native-new-architecture. Gdy Nowa Architektura stanie się domyślna, te informacje zostaną włączone do reactnative.dev.

Nowa Architektura: Zgrupowane aktualizacje onLayout

Aktualizacje stanu w callbackach onLayout są teraz grupowane. Wcześniej każda aktualizacja stanu w zdarzeniu onLayout powodowała nowe zatwierdzenie renderowania.

function MyComponent(props) {
const [state1, setState1] = useState(false);
const [state2, setState2] = useState(false);

return (
<View>
<View
onLayout={() => {
setState1(true);
}}>
<View
onLayout={() => {
// When this event is executed, state1's new value is no longer observable here.
setState2(true);
}}>
</View>
</View>
);
}

W wersji 0.74 aktualizacje setState1 i setState2 są grupowane razem. To zachowanie jest oczekiwane w React i pozwala na mniejszą liczbę ponownych renderowań.

niebezpieczeństwo

Ta zmiana może zepsuć kod, który opierał się na niegrupowanych aktualizacjach stanu. Konieczne będzie przepisanie takiego kodu przy użyciu funkcji aktualizujących lub ekwiwalentnych rozwiązań.

Yarn 3 dla nowych projektów

Yarn 3 jest teraz domyślnym menedżerem pakietów JavaScript dla nowych projektów inicjowanych przez React Native Community CLI.

Yarn 3.x będzie używany z opcją nodeLinker: node-modules, zapewniającą kompatybilność z bibliotekami React Native. Zastępuje to Yarn Classic (1.x, przestarzały) jako poprzednie domyślne rozwiązanie. Aby zaktualizować Yarn w istniejącej aplikacji, skorzystaj z tego przewodnika.

$ yarn --help
━━━ Yarn Package Manager - 3.6.4 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

$ yarn <command>

Community CLI obsługuje także inicjowanie projektów z innymi menedżerami pakietów poprzez flagę --pm (więcej informacji).

Zmiany łamiące kompatybilność

Nowe minimalne wymaganie SDK dla Androida (Android 6.0)

React Native 0.74 wymaga minimalnej wersji Android SDK 23 (Android 6.0). Poprzednio było to Android 5.0 (API 21). Kontekst tej zmiany opisaliśmy tutaj.

Bonus: redukcja rozmiaru aplikacji na Androida

Podniesienie minimalnego SDK wraz z kilkoma ulepszeniami w natywnej kompilacji pozwoliło znacznie zmniejszyć rozmiar aplikacji na urządzeniach użytkowników.

Np. nowo utworzona aplikacja w React Native 0.74 zajmuje o ~13% mniej miejsca na urządzeniu, co daje oszczędność ~4MB.

Porównanie rozmiarów nowej aplikacji React Native w widoku pamięci systemowej Androida

Usunięcie przestarzałych PropTypes

Przed wersją 0.74 React Native dostarczał PropTypes - API zdeprecjonowane od React 15.5 w 2017 roku! Teraz usuwamy wszystkie wbudowane PropTypes, redukując rozmiar aplikacji (26.4kB w zminimalizowanym bundle) i obciążenie pamięci.

Usunięto następujące właściwości PropTypes: Image.propTypes, Text.propTypes, TextInput.propTypes, ColorPropType, EdgeInsetsPropType, PointPropType, ViewPropTypes (zobacz commit).

Jeśli Twoja aplikacja lub biblioteka używa PropTypes, zalecamy migrację do systemu typów jak TypeScript.

Zmiany API w PushNotificationIOS (zdeprecjonowane)

W React Native 0.74 podejmujemy kroki ku usunięciu przestarzałej biblioteki PushNotificationIOS. Zmiany w tej wersji koncentrują się na usunięciu referencji do starszych iOS API. PushNotificationIOS został zmigrowany na framework User Notifications Apple'a i udostępnia nowe API do planowania i obsługi powiadomień.

W kolejnej wersji (0.75) planujemy całkowite usunięcie tej biblioteki z rdzenia React Native i przeniesienie do pakietu społecznościowego @react-native-community/push-notification-ios. Jeśli nadal korzystasz z PushNotificationIOS, musisz przeprowadzić migrację przed następnym wydaniem.

Zmiany API

Callback didRegisterUserNotificationSettings: w RCTPushNotificationManager był nieużywany i został usunięty.

Następujące callbacki w RCTPushNotificationManager zostały oznaczone jako przestarzałe i zostaną usunięte w wersji 0.75:

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

Aby pobrać powiadomienie, które uruchomiło aplikację za pomocą getInitialNotification(), musisz teraz jawnie ustawić initialNotification w RCTPushNotificationManager:

[RCTPushNotificationManager setInitialNotification:response.notification];

Po stronie JavaScript zmieniły się właściwości w Notification. alertAction i repeatInterval są teraz przestarzałe i zostaną usunięte w wersji 0.75:

type Notification = {
...
// NEW: Seconds from now to display the notification.
fireIntervalSeconds?: ?number,

// CHANGED: Used only for scheduling notifications. Will be null when
// retrieving notifications using `getScheduledLocalNotifications` or
// `getDeliveredNotifications`.
soundName?: ?string,

// DEPRECATED: This was used for iOS's legacy UILocalNotification.
alertAction?: ?string,

// DEPRECATED: Use `fireDate` or `fireIntervalSeconds` instead.
repeatInterval?: ?string,
};

Wreszcie, nieużywany parametr handler w PushNotificationIOS.removeEventListener został usunięty.

💡 How to Migrate

iOS

Your AppDelegate will need to implement UNUserNotificationCenterDelegate. This should be done on app startup in application:willFinishLaunchingWithOptions: or application:didFinishLaunchingWithOptions: (see Apple Docs for more details).

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;

return YES;
}

Implement userNotificationCenter:willPresentNotification:withCompletionHandler:, which is called when a notification arrives and the app is in the foreground. Use the completionHandler to determine if the notification will be shown to the user and notify RCTPushNotificationManager accordingly:

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
// This will trigger 'notification' and 'localNotification' events on PushNotificationIOS
[RCTPushNotificationManager didReceiveNotification:notification];
// Decide if and how the notification will be shown to the user
completionHandler(UNNotificationPresentationOptionNone);
}

To handle when a notification is tapped, implement userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:. Note that if you set foreground notifications to be shown in userNotificationCenter:willPresentNotification:withCompletionHandler:, you should only notify RCTPushNotificationManager in one of these callbacks.

If the tapped notification resulted in app launch, call setInitialNotification:. If the notification was not previously handled by userNotificationCenter:willPresentNotification:withCompletionHandler:, call didReceiveNotification: as well:

- (void)  userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
// This condition passes if the notification was tapped to launch the app
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
// Allow the notification to be retrieved on the JS side using getInitialNotification()
[RCTPushNotificationManager setInitialNotification:response.notification];
}
// This will trigger 'notification' and 'localNotification' events on PushNotificationIOS
[RCTPushNotificationManager didReceiveNotification:response.notification];
completionHandler();
}

Finally, delete the following methods and adapt the logic into the callbacks above which will be called instead:

  1. application:didReceiveLocalNotification: [deprecated]
  2. application:didReceiveRemoteNotification: [deprecated]
  3. application:didReceiveRemoteNotification:fetchCompletionHandler: [not deprecated, but is superseded by the UNUserNotificationCenterDelegate methods]

Delete any usages of application:didRegisterUserNotificationSettings: and RCTPushNotificationManager’s corresponding didRegisterUserNotificationSettings: as well.

Example: See the RNTester AppDelegate.mm.

JS

  1. Remove any references to alertAction.
  2. Remove the handler argument on any calls to removeEventListener.
  3. Replace any usages of repeatInterval by firing multiple notifications using fireDate or fireIntervalSeconds instead.
  4. Note that soundName will be null when it is accessed on a Notification returned from getScheduledLocalNotifications() and getDeliveredNotifications().

Usunięcie wtyczki Flipper React Native

Korzystanie z Flippera do inspekcji układów React Native, żądań sieciowych i innych funkcji wtyczek React Native nie jest już wspierane. W wersji 0.74 usunęliśmy natywne biblioteki Flippera i kod konfiguracyjny z nowych projektów React Native. Oznacza to mniej zależności i szybszą lokalną konfigurację (zobacz oryginalny RFC).

Różnicę w usunięciu Flippera w twojej aplikacji można zobaczyć w Upgrade Helper. Jeśli chcesz zachować Flippera w istniejącej aplikacji, zignoruj odpowiednie linie różnic.

💡 To re-integrate Flipper

Flipper can still be used as a standalone tool for debugging an Android or iOS app, and can be manually integrated by following the Flipper docs (Android guide, iOS guide).

We recommend that teams invest in switching to native debugging tooling in Android Studio and Xcode.

wskazówka

Zastępowanie Flippera

Istnieje kilka dedykowanych narzędzi do debugowania, które zastępują funkcje Flippera. Więcej informacji znajdziesz w doskonałym artykule Jamona Holmgrena Dlaczego nie potrzebujesz Flippera w swojej aplikacji React Native.

Debugowanie JavaScript

Debugger Hermesa pozostaje naszą rekomendowaną opcją debugowania dla wersji 0.74. Możesz też wypróbować Eksperymentalny Nowy Debugger, który jest również domyślny w Expo. To nadal wczesna wersja preview — znane problemy i aktualizacje można śledzić tutaj.

Inne zmiany łamiące kompatybilność

Ogólne

  • Właściwości start/end w stylach zawsze odnoszą się teraz do kierunku pisania (#42251).

Android

  • Usunięto JSIModule* z FabricUIManagerProvider (#42059).

    • To API nie było używane w open source — zamiast tego użyj TurboModules.
  • Oznaczono jako przestarzałe UIManagerModule.showPopupMenu i UIManagerModule.dismissPopupMenu (#42441)

iOS

  • Usunięto argumenty configFilename i configKey z CLI generującego kod na iOS (#41533).

  • Zmiana obsługi bundleURL (#43994).

    • Wcześniej bundleURL był ustawiany przy starcie React Native jako zmienna instancji i nie można go było aktualizować.
    • Teraz bundleUrl jest funkcją, która jest ponownie wyliczana w razie potrzeby, umożliwiając użycie innego adresu URL przy odświeżaniach.
    • Ta zmiana wpłynie na twoją aplikację tylko wtedy, gdy modyfikowałeś zmienną bundleURL po uruchomieniu aplikacji. W takim przypadku przenieś logikę aktualizującą zmienną do funkcji bundleURL w AppDelegate.

Pełną listę zmian łamiących kompatybilność znajdziesz w pełnym dzienniku zmian.

Znane problemy

iOS

  • Szczególny przypadek przy używaniu wielu okien: Gdy główne okno jest nieaktywne, a system próbuje wyświetlić okno dialogowe, dialog nie pojawia się w odpowiedniej pozycji na ekranie. Poprawka jest w trakcie implementacji w #44167 i zostanie wydana w wersji 0.74.1.

Podziękowania

React Native 0.74 zawiera ponad 1673 commity od 57 współtwórców. Dziękujemy za waszą ciężką pracę!

Dziękujemy wszystkim dodatkowym autorom, którzy pracowali nad dokumentowaniem funkcji w tym poście o wydaniu:

Aktualizacja do wersji 0.74

Do sprawdzenia zmian kodu między wersjami React Native w istniejących projektach użyj React Native Upgrade Helper, dodatkowo do dokumentacji aktualizacji.

Aby utworzyć nowy projekt:

npx react-native@latest init MyProject

Jeśli używasz Expo, React Native 0.74 będzie obsługiwany w Expo SDK 51.

informacja

0.74 jest teraz najnowszą stabilną wersją React Native, a wersja 0.71.x przechodzi do nieobsługiwanych. Więcej informacji znajdziesz w polityce wsparcia React Native. Planujemy opublikować końcową aktualizację końca wsparcia dla wersji 0.71 na początku maja.