Czy istnieje systematyczne podejście do debugowania tego, co powoduje ponowne renderowanie komponentu w Reakcie? Umieściłem prostą console.log (), aby zobaczyć, ile razy renderuje, ale mam problem ze zrozumieniem, co powoduje, że komponent renderuje się wiele razy, tj. (4 razy) w moim przypadku. Czy istnieje narzędzie, które pokazuje oś czasu i / lub wszystkie renderowane i porządkowane drzewo komponentów?
156
shouldComponentUpdate
się wyłączenie automatycznej aktualizacji komponentów, a następnie rozpoczęcie śledzenia z tego miejsca. Więcej informacji można znaleźć tutaj: facebook.github.io/react/docs/optimizing-performance.htmlOdpowiedzi:
Jeśli chcesz krótki fragment bez żadnych zewnętrznych zależności, uważam to za przydatne
Oto mały haczyk, którego używam do śledzenia aktualizacji komponentów funkcji
źródło
setState
metodę (w komponencie klasy),setState(...args) { super.setState(...args) }
a następnie ustawić punkt przerwania w debugerze, który będziesz mógł wtedy aby prześledzić z powrotem do funkcji ustawiającej stan.useTraceUpdate
po zdefiniowaniu tego, co napisałeś?function MyComponent(props) { useTraceUpdate(props); }
i będzie zalogować ilekroć rekwizyty zmianthis.state
jest niezdefiniowany.Oto kilka przypadków ponownego renderowania komponentu React.
this.setState()
w ramach komponentu. Spowoduje to następujące metody elementów cyklu życiashouldComponentUpdate
>componentWillUpdate
>render
>componentDidUpdate
props
. To spowodujecomponentWillReceiveProps
>shouldComponentUpdate
>componentWillUpdate
>render
>componentDidUpdate
(connect
metodareact-redux
wyzwalania to gdy istnieją obowiązujące zmiany w sklepie Redux)this.forceUpdate
które jest podobne dothis.setState
Możesz zminimalizować ponowne wyrejestrowanie komponentu, wdrażając sprawdzenie wewnątrz swojego
shouldComponentUpdate
i zwracając,false
jeśli nie jest to konieczne.Innym sposobem jest użycie
React.PureComponent
komponentów bezstanowych. Czyste i bezstanowe komponenty renderują się ponownie tylko wtedy, gdy są zmiany w ich właściwościach.źródło
shouldComponentUpdate
lub rozszerzyćReact.PureComponent
, aby wymusić ponowne renderowanie tylko w przypadku zmiany.const MyComponent = (props) => <h1>Hello {props.name}</h1>;
(To jest komponent bezstanowy). Wyrenderuje się ponownie przy każdym ponownym renderowaniu komponentu nadrzędnego.Odpowiedź @jpdelatorre świetnie podkreśla ogólne powody, dla których składnik React może renderować się ponownie.
Chciałem tylko zagłębić się w jeden przykład: kiedy zmieniają się rekwizyty . Rozwiązywanie tego, co powoduje ponowne renderowanie komponentu React, jest częstym problemem, az mojego doświadczenia wynika, że często śledzenie tego problemu wymaga określenia, które właściwości ulegają zmianie .
Komponenty React renderują się ponownie, gdy otrzymają nowe rekwizyty. Mogą otrzymać nowe rekwizyty, takie jak:
<MyComponent prop1={currentPosition} prop2={myVariable} />
lub jeśli
MyComponent
jest podłączony do sklepu Redux:Anytime wartość
prop1
,prop2
,prop3
, czyprop4
zmianyMyComponent
będą ponownie render. Przy 4 rekwizytach nie jest zbyt trudno wyśledzić, które rekwizyty się zmieniają, umieszczającconsole.log(this.props)
na tym początkurender
bloku. Jednak przy bardziej skomplikowanych komponentach i coraz większej liczbie rekwizytów ta metoda jest nie do utrzymania.Oto przydatne podejście (przy użyciu lodash dla wygody) do określenia, które zmiany właściwości powodują ponowne renderowanie komponentu:
Dodanie tego fragmentu kodu do komponentu może pomóc w ujawnieniu sprawcy powodującego wątpliwe ponowne renderowanie, a często pomaga to rzucić światło na niepotrzebne dane przesyłane potokiem do komponentów.
źródło
UNSAFE_componentWillReceiveProps(nextProps)
i jest przestarzałe. „Ten cykl życia był wcześniej nazwanycomponentWillReceiveProps
. Ta nazwa będzie działać aż do wersji 17.” Z dokumentacji Reacta .Dziwne, że nikt nie udzielił takiej odpowiedzi, ale uważam ją za bardzo przydatną, zwłaszcza że zmiany rekwizytów są prawie zawsze głęboko zagnieżdżone.
Miłośnicy haków:
„Starzy” fani szkolni:
PS Nadal wolę używać HOC (komponent wyższego rzędu), ponieważ czasami zniszczyłeś swoje rekwizyty na górze, a rozwiązanie Jacoba nie pasuje
Zastrzeżenie: brak jakiegokolwiek powiązania z właścicielem pakietu. Samo kliknięcie dziesiątki razy dookoła, aby spróbować dostrzec różnicę w głęboko zagnieżdżonych obiektach, jest uciążliwe.
źródło
Na npm jest teraz dostępny haczyk do tego:
https://www.npmjs.com/package/use-trace-update
(Ujawnienie, opublikowałem) Aktualizacja: Opracowana w oparciu o kod Jacoba Raska
źródło
Używając haków i elementów funkcjonalnych, nie tylko zmiana rekwizytu może spowodować wycofanie się. Zacząłem używać raczej ręcznego dziennika. Bardzo mi pomogłem. Może ci się też przydać.
Wklejam tę część do pliku komponentu:
Na początku metody mam odniesienie do WeakMap:
Następnie po każdym „podejrzanym” wezwaniu (rekwizyty, haki) piszę:
źródło
Powyższe odpowiedzi są bardzo pomocne, na wypadek gdyby ktoś szukał konkretnej metody wykrywania przyczyny ponownego renderowania to znalazłem tę bibliotekę redux-logger bardzo pomocna.
To, co możesz zrobić, to dodać bibliotekę i włączyć różnicowanie między stanami (jest w dokumentacji), na przykład:
I dodaj oprogramowanie pośredniczące w sklepie.
Następnie umieść
console.log()
w funkcji renderowania komponentu, który chcesz przetestować.Następnie możesz uruchomić aplikację i sprawdzić, czy są dzienniki konsoli. Gdziekolwiek jest dziennik tuż przed, pokaże Ci różnicę między stanami
(nextProps and this.props)
i możesz zdecydować, czy renderowanie jest tam naprawdę potrzebneBędzie podobny do powyższego obrazu wraz z kluczem diff.
źródło