2016-08-02 31 views
6

Podczas nawigacji w dużej aplikacji Native React z wykorzystaniem Redux wszystkie odwiedzane sceny (sceny ze stosu nawigacji) są montowane. Wszystkie te sceny otrzymują rekwizyty i są renderowane w kolejności, w jakiej zostały odwiedzone, gdy jakakolwiek akcja zostanie wysłana z ostatniego komponentu sceny. Powoduje zamrożenia i widoczne opóźnienia między wysyłaniem i ostatnim renderowaniem sceny.Możliwy problem z nawigacją w aplikacji React Native/Redux

Do nawigacji używam react-native-router-flux, ale ten sam problem występuje również w oryginalnym React Native Navigator.

Wideo Possible navigation issues in React Native/Redux app

Kod react-redux-navigation-test

Byłoby miło wiedzieć, jak zapobiegać przechodzących rekwizyty nie skoncentrowane składniki z łańcucha nawigacji.

W tej chwili sprawdzam w shouldComponentUpdate każdego komponentu, jeśli ten jest skupiony (widoczny) i zwraca false w przeciwnym przypadku.

Czy istnieje lepsze rozwiązanie?

+0

HI! Mam taki sam problem z moją aplikacją RN. Czy znalazłeś jakiś sposób, aby go rozwiązać? – David

Odpowiedz

0

Nie korzystałem z routera reagowania na macierzysty router, jednak mam doświadczenie z dość dużą aplikacją React Native i Redux. Zauważyłem, że czasami, jeśli dane, z którymi pracujesz, są wystarczająco duże, mogą powodować zauważalne opóźnienia, ale są one ograniczone głównie do pracy nad programowaniem. Kiedy aplikacja jest zbudowana, zwykle jest zauważalnie szybsza. Wygląda na to, że Redux robi rzeczy nieco inaczej w trybach rozwoju i produkcji.

Odnośnie scen w stosie nawigacyjnym, który wciąż jest montowany, jest to zgodne z projektem. Nawet gdy od navigator.push do innego ekranu te poprzednie ekrany pozostają zamontowane, dopóki nie zostaną wyrzucone z currentRouteStack lub wymienione na currentRouteStack.

Warto również zauważyć, że Twój symulator znajduje się w trybie Wolnych Animacji. Nie jestem pewien, czy zrobiłeś to dla sake wideo, czy nie, ale powolność nawigacji jest po części z tego powodu. Tylko heads-up w przypadku, który nie był celowy.

Chciałbym sprawdzić, jak aplikacja wydaje się działać po zbudowaniu i nie jest w trybie programowania, zanim rozwiąże problemy z wydajnością znacznie dalej. Może nie być problemem dla końcowego produktu aplikacji.

+0

Dziękuję za tak szybką odpowiedź. Ten problem występuje również na prawdziwym urządzeniu w trybie produkcji. Opóźnienia te zależą głównie od tego, jak duże są sceny ze stosu nawigacyjnego. W powyższym przykładzie na scenie startowej wyświetlana jest ogromna lista 1000 elementów, aby podkreślić te opóźnienia. W prawdziwej aplikacji pracuję nad tymi opóźnieniami nie są tak duże, ale znaczące. Przejścia między scenami w przykładzie na wideo równym 2s. Nie tryb wolny. Poszukuję więc lepszego sposobu na zapobieganie renderowaniu, a nawet przechodzeniu rekwizytów dla niewidocznych scen. W tej chwili korzystam z check in shouldComponentUpdate – alexsh

+0

Hmmm, co ciekawe. Widzę, że renderujesz te elementy w ScrollView. Byłbym ciekawy, co ListView zrobi dla wydajności. Sądzę, że są dodatkowe ulepszenia wydajności, których używają do renderowania wierszy ListView. Może warto zaglądać. – jasonmerino

2

Zaleca się obliczenie odległości sceny między bieżącą sceną a sceną renderowaną za pomocą indeksu nawigacji w scenie i metod renderowania nagłówka. Jeśli odległość> 1 zwraca wartość null.

To powinno uniemożliwić renderowanie całej historii nawigacji. Nie ma dla mnie żadnego sensu, aby tego rodzaju zachowanie nie było dostępne po wyjęciu z pudełka, ale tak właśnie jest.

0

Mam zamiar wyjść tutaj, ale czy używasz jednej z poniższych metod, aby zapobiec ponownemu renderowaniu?

  • PureComponents (dodane w React 15,3 myślę)
  • ręcznie z płytkich porównać rekwizyty i państwa ze sposobu shouldComponentUpdate.

Domyślnie React ponownie renderuje wszystkie komponenty po aktualizacji, chyba że poprawnie obsłużysz metodę shouldComponentUpdate.

robię coś podobnego, a nie o te kwestie w ogóle

0

Problem polega na tym, że rzeczywiście cały stos nawigacji jest podłączony do sklepu (bo komponenty nie są odmontowana chyba użyć resetto lub resetnavigation)

To, co tu jest warte, to to, co robię teraz. pracuję z lekko zmodyfikowanym reagować Redux realizacji że przeskakuje aktualizacje dla scen, które nie są w widoku (patrz niżej)

Aby z niego skorzystać należy:

Store trasa na drzewie jeden składnik w kontekście

stworzyliśmy opakowanie dla tego

const CurrentRoute = React.createClass({ 
childContextTypes : { currentRoute: PropTypes.object }, 
getChildContext() { 
return { currentRoute: this.props.route } 
}, 
render() { return this.props.children; } 
}) 

i używać go w renderowanie scena

<CurrentRoute route={route}><CurrentScene navigate={navigate} route={route} index={index} /></CurrentRoute> 

Następnie można uzyskać dostęp do trasy, na której został wyrenderowany komponent.

Store stos nawigacji w Singleton Używamy ten kod w configure sceny

let routeStack = []; 
export const updateRouteStack = stack => routeStack = stack; 

Następnie można użyć tego lekko zmodyfikowaną funkcję reagowania-Redux połączyć, to pomiń aktualizacje jeśli składnik jest renderowany w innym składniku drzewo następnie aktualnie wyświetlany (lub podobna implementacja) https://github.com/reactjs/react-redux/compare/master...ganmor:master

Możliwe, że można to spakować, ale nie miałem czasu na zaglądanie. Jeśli ktoś ma ochotę to zrobić ... Nadzieję, że pomaga

0

Rozwiązaliśmy to po prostu zawijając wszystkie ekrany w komponencie.

Mamy jeden komponent ScreenView, który otacza cały ekran i przekazujemy mu parametr "restrictRerendersToRoutes".

Ten ekran jest podłączony do stanu, a my aktualizujemy currentScrene w naszym stanie i wystawiamy go na ten widok ekranu.

Potem wystarczy ograniczyć rerenders gdy ekran jest w tle z tej implementacji shouldComponentUpdate:

shouldComponentUpdate(nextProps) { 
    if (!_.empty(this.props.restrictRerendersToRoutes)) { 
     return !!this.props.restrictRerendersToRoutes 
     .find((routeKey) => routeKey === nextProps.currentScene.name); 
    } 

    return true; 
    } 
+0

Czy możesz podać bardziej szczegółowy przykład, byłoby to naprawdę pomocne. Dziękuję Ci! – David