Specyfikacja ES2023 wprowadza teraz cztery metody tablic — toSorted, toReversed, toSpliced oraz with — które zwracają nowe tablice zamiast mutować oryginalną. W React oraz innych bibliotekach UI opartych na niezmiennych (immutable) stanach, pomocniki te pozwalają programistom zastąpić sztuczki z operatorem spread, które od dawna były źródłem błędów i powtarzalnego kodu (boilerplate).
Dlaczego ta zmiana jest ważna
React decyduje o tym, czy ponownie wyrenderować komponent, porównując referencję poprzedniego stanu z nową. Jeśli referencja pozostaje bez zmian, React zakłada, że nic się nie zmieniło. Klasyczna metoda Array.prototype.sort sortuje tablicę w miejscu i zwraca tę samą referencję, więc wywołanie typu setTasks(prev => prev.sort(fn)) sprawia, że React nie zauważa aktualizacji. Interfejs użytkownika pozostaje z nieaktualnymi danymi — jest to błąd, który bardzo często pojawia się w rzeczywistych projektach.
Programiści obchodzili ten problem, najpierw klonując tablicę — zazwyczaj za pomocą operatora spread — tak aby krok sortowania generował nową referencję:
setTasks(prev => [...prev].sort((a, b) => b.priority - a.priority));
Ten wzorzec działa, ale wprowadza niepotrzebny szum w kodzie i łatwo o nim zapomnieć. Nowe metody ES2023 oferują bezpośredni i czytelny sposób na utworzenie nowej tablicy przy zachowaniu oryginalnej nienaruszonej.
Cztery metody nie zmieniające stanu (non-mutating)
toSorted(compareFn?)– zachowuje się jaksort, ale zwraca posortowaną kopię. Brak zmian w tablicy źródłowej.toReversed()– zastępujereverse. Zwraca odwróconą kopię, pozostawiając oryginalną kolejność nienaruszoną.toSpliced(start, deleteCount, ...items)– odzwierciedlasplicebez efektów ubocznych. Zwrócona tablica uwzględnia wstawienie lub usunięcie, a źródło pozostaje bez zmian.with(index, value)– podmienia element na pozycjiindexnavaluei zwraca nową tablicę. Zastępuje powszechny wzorzec użyciamaplub operatora spread do podmiany elementu.
Wszystkie cztery metody są częścią standardu ECMAScript i są dostępne w aktualnych wersjach głównych przeglądarek oraz w Node.js 20.
Jak wygląda teraz kod
Sortowanie listy
// Before
setTasks(prev => [...prev].sort((a, b) => b.priority - a.priority));
// After
setTasks(prev => prev.toSorted((a, b) => b.priority - a.priority));
Aktualizacja pojedynczego elementu
// Before
setItems(prev =>
prev.map((item, i) => (i === idx ? newItem : item))
);
// After
setItems(prev => prev.with(idx, newItem));
Odwracanie tablicy
setLogs(prev => prev.toReversed());
Usuwanie elementu
setTags(prev => prev.toSpliced(removeIdx, 1));
Nowa składnia eliminuje potrzebę stosowania dodatkowych operatorów spread lub pętli mapujących, dzięki czemu aktualizacje stanu są łatwiejsze do odczytania i mniej podatne na błędy.
Kto zyskuje, a kto może się wahać
Programiści korzystający z React, Vue, Redux, Zustand lub jakiegokolwiek frameworka oczekującego niezmiennych struktur danych, zyskują jaśniejszy model mentalny: wywołujesz metodę, otrzymujesz nową tablicę i przekazujesz ją do funkcji ustawiającej (setter). Redukcja boilerplate'u może również skrócić cykle renderowania o kilka milisekund, ponieważ silnik unika tworzenia pośredniej kopii przed sortowaniem.
Zespoły obsługujące starsze przeglądarki mogą potrzebować polyfillów. Metody te nie występują w starszych wersjach Safari czy Internet Explorera, więc build produkcyjny celujący w te platformy musi zawierać rozwiązanie zastępcze (fallback). Dodaje to niewielki koszt w postaci rozmiaru paczki (bundle size), ale zysk w czytelności jest zazwyczaj tego wart.
Autorzy bibliotek mogą potrzebować aktualizacji definicji typów (np. TypeScript), aby udostępnić nowe sygnatury. Dopóki te definicje nie trafią do oficjalnych pakietów @types, programiści mogą napotykać tymczasowe błędy typów.
Na co warto zwrócić uwagę
- Metryki adopcji – narzędzia takie jak ESLint mogą wkrótce dodać reguły flagujące mutowalne wywołania tablic w setterach stanu, zachęcając programistów do korzystania z nowych metod.
- Badania wydajności – wczesne benchmarki sugerują, że natywne metody nie zmieniające stanu są szybsze niż klonowanie operatorem spread, a następnie operacja mutująca, ale rzeczywiste dane potwierdzą ten wpływ.
- Dalsze propozycje – komitet ECMAScript kontynuuje badanie API domyślnie niezmiennych (immutable-by-default); śledzenie nadchodzących etapów może ujawnić więcej pomocników pasujących do tego samego wzorca.
Podsumowanie
Najnowsza specyfikacja ECMAScript daje programistom UI wbudowany, zwięzły sposób na zachowanie niezmienności stanu bez akrobatyki z operatorem spread, która powodowała niezliczone błędy. Podmieniając sort, reverse, splice oraz podmiany oparte na indeksie na toSorted, toReversed, toSpliced i with, pozwalasz mechanizmowi wykrywania zmian w React działać zgodnie z przeznaczeniem i sprawiasz, że Twój kod jest łatwiejszy do odczytania. Jeśli Twoje docelowe przeglądarki obsługują nowe metody — lub jesteś gotów użyć polyfilli — nadszedł czas, aby wycofać stare wzorce i pozwolić językowi wykonać najcięższą pracę.
