Czym jest Strict Mode w React?

React rozwija się niezwykle dynamicznie i praktycznie z każdą kolejną aktualizacją programiści otrzymują także nowe API. W wersji 16 wprowadzono wiele ciekawych mechanizmów, a jednym z nich jest dość niedoceniany Strict Mode.

A dokładniej mowa o wersji 16.3 Reacta, bo to właśnie w tej wersji zadebiutował Strict Mode.
W dużym uproszczeniu: Strict Mode to po prostu komponent, który pozwala na włączenie mechanizmu ostrzegania przed potencjalnymi problemami w aplikacji. Np. jeżeli używamy przestarzałych metod w komponentach klasowych, zostaniemy o tym poinformowani.

Pomimo iż <React.StrictMode /> jest komponentem, jest on absolutnie transparentny dla interfejsu użytkownika, co sprawia, że bliżej mu do Fragmentu niż do zwykłych komponentów.
Więcej o fragmentach możecie przeczytać w tym poście. No dobrze, dowiedzmy się nieco więcej o Strict Mode.



A komu to potrzebne?

No właśnie! Przecież dobrze skonfigurowany linter też wskaże potencjalne problemy!
I tak i nie. Narzędzie ESlint posiada zbiór rekomendowanych reguł dla Reacta, ale nie powie nam, że np. używanie componentWillReceiveProps to nie jest obecnie najlepszy pomysł. Oczywiście reguły eslinta możemy rozszerzać, pisać własne pluginy, ale to zdecydowanie więcej pracy niż podpięcie Strict Mode. Poza tym kto wie co w kolejnej wersji Reacta zostanie oznaczone jako deprecated?

Nawet gdybyśmy stworzyli idealny plugin do naszego lintera i aktualizowali go na bieżąco, to i tak pozbawimy się kilku istotnych zalet trybu ścisłego:

1. Można go włączać na różnym poziomie hierarchii komponentów

Przede wszystkim nie musimy go włączać dla całej struktury projektu, ale np. dla określonego drzewa komponentów. Istnieje potrzeba zrefaktoryzować pasek boczny? Nie ma sprawy! Wystarczy opakować tylko ten element aplikacji komponentem <React.StrictMode /> i będziemy ostrzegani o problemach tylko w jego obszarze. W przypadku lintera byłoby to nieco bardziej kłopotliwe, ponieważ musielibyśmy wykluczać, które pliki lub kawałki kodu mają nie być analizowane. Jest to możliwe, ale po co sobie utrudniać życie?

2. Uruchamia pewne części kodu dwukrotnie

I to nie jest żart, w żadnym wypadku. Pozwala to na zdiagnozowanie potencjalnych efektów ubocznych (ang. side effects), które mogą pojawić się jeszcze przed samym wyrenderowaniem komponentu. Poniżej lista metod wywoływanych dwukrotnie:

  • constructor – czyli metoda wywoływana przy tworzeniu komponentu klasowego
  • setState – metoda aktualizująca stan, wywoływana tylko z pierwszym argumentem
  • render – metoda renderująca obiekt
  • getDerivedStateFromProps – statyczna metoda wywoływana przy zmianie stanu i propsów

Dla fanów podejścia funkcyjnego: również hooki takie jak useState czy useMemo są wywoływane dwukrotnie. Pytanie tylko po co? Takie zachowanie jest spowodowane tym, że tryb ścisły nie potrafi sam z siebie wykryć efektów ubocznych. Musimy mu w tym pomóc. To my znamy naszą aplikację i wiemy jakie zachowania będą błędne i niepożądane. Dwukrotne wywoływanie powyższych metod pozwala zdiagnozować czy fragmenty kodu w nich zawarte są idempotentne. Trudne słowo prawda? Oznacza właściwość instrukcji, która sprawia, że jej wielokrotne wywoływanie zwróci nam ten sam rezultat. Sprawdzamy więc po prostu czy nasz kod jest przewidywalny w zachowaniu.

3. Analizuje także zewnętrzne biblioteki

Co może być zarówno wadą jak i zaletą. Z jednej strony dzięki temu jesteśmy pewni, że nasze zewnętrzne zależności spełniają podstawowe kryteria co do jakości kodu. Z drugiej zaś nie zawsze nas to interesuje. Czasem chcemy po prostu podpiąć na szybko dodatkową paczkę i tyle. Możemy to obejść wyciągając zewnętrzny komponent poza <React.StrictMode />.

4. Nie jest uruchamiany w trybie produkcyjnym

Można by zaryzykować stwierdzenie, że np. dwukrotne uruchamianie niektórych metod może mieć wpływ na szybkość działania aplikacji. Na szczęście Strict Mode jest uruchamiany tylko w trybie deweloperskim i po zbudowaniu projektu w trybie produkcji, jest on zupełnie wyłączany. Nie musimy więc robić tego sprawdzania sami i wprowadzać znaczących różnic w kodzie między wersjami Dev i Prod.

Włączamy Strict Mode

Skoro już wiemy, że tryb ścisły ma swoje zalety, sprawdźmy jak to działa w praktyce. Nie musimy w tym celu instalować żadnej zewnętrznej zależności, ponieważ Strict Mode jest częścią paczki Reacta. W najprostszej wersji wystarczy więc opakować główny komponent aplikacji w komponent trybu ścisłego:

import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom';
 
ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  document.getElementById('root')
);

I to dosłownie wszystko. Opakowując w ten sposób nasz główny komponent sprawimy, że tryb ścisły zacznie informować nas o potencjalnych problemach w całej aplikacji. Przykładowy warning może wyglądać następująco:

Warning: Unsafe lifecycle methods were found within a strict-mode tree:
    in StrictMode

componentWillMount: Please update the following components to use componentDidMount instead: WillMount

Learn more about this warning here:
https://fb.me/react-strict-mode-warnings

Oczywiście jak już wspomniałem wcześniej, tryb ścisły może także opakowywać tylko określone komponenty. Rozwińmy nasz komponent <App /> jako prosty komponent funkcyjny składający się z kilku mniejszych:

import React, { StrictMode } from 'react';

const App = () => (
  <div>
    <header>Przykładowa apka</header>
    <StrictMode>
      <aside>Sidebar w trybie ścisłym</aside>
    </StrictMode>
    <main>
      content...
    </main>
    <footer>Przykładowy footer</footer>
  </div>
);

W tym wypadku tryb ścisły obejmie jedynie kod znajdujący się w znaczniku <aside />. I to na prawdę wszystko co musimy zrobić aby pracować ze Strict Mode. Gdyby wszystko było tak proste 😉

Podsumowanie

Tryb ścisły to całkiem ciekawy sposób na analizę projektów Reactowych pod kątem dobrych wzorców i unikania używania przestarzałego API. Na pewno nie jest to lek na całe zło i nie unikniemy w ten sposób wszystkich błędów, ale z pewnością pomoże nam pisać aplikacje na pewnym ustandaryzowanym poziomie. To także świetne narzędzie do wspomagania wyrabiania sobie dobrych praktyk w zabawach z Reactem.

Włączenie tego trybu jest banalnie proste, a sama aplikacja nie przestanie nam działać nawet gdy w konsoli pojawią się setki ostrzeżeń. Dlatego też gorąco zachęcam do próbowania włączenia go w swoich projektach i sprawdzenia się czy rzeczywiście jesteśmy tak bezbłędni jak myślimy 😉 Dobrego kodzenia!