From 1f35faa5651c25544cd70d1ba9fd392494069ff4 Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Mon, 11 Nov 2024 00:24:09 +0100 Subject: [PATCH] Learn / Preserving and resetting state (#490) --- src/content/learn/managing-state.md | 4 +- .../learn/preserving-and-resetting-state.md | 388 +++++++++--------- src/content/reference/react/useState.md | 2 +- src/sidebarLearn.json | 2 +- 4 files changed, 198 insertions(+), 198 deletions(-) diff --git a/src/content/learn/managing-state.md b/src/content/learn/managing-state.md index df2b85dca..8208ea68f 100644 --- a/src/content/learn/managing-state.md +++ b/src/content/learn/managing-state.md @@ -300,7 +300,7 @@ Przeczytaj rozdział pt. **[Współdzielenie stanu między komponentami](/learn/ -## Utrzymywanie i resetowanie stanu {/*preserving-and-resetting-state*/} +## Zachowywanie i resetowanie stanu {/*preserving-and-resetting-state*/} Kiedy ponownie renderujesz komponent, React musi zdecydować, które części drzewa należy zostawić (i zaktualizować), a które odrzucić lub stworzyć na nowo. W większości przypadków React sam zdecyduje, co należy zrobić. Domyślnie React zachowuje części drzewa, które pokrywają się z poprzednim drzewem komponentów. @@ -496,7 +496,7 @@ textarea { -Przeczytaj rozdział pt. **[Utrzymywanie i resetowanie stanu](/learn/preserving-and-resetting-state)**, aby nauczyć się cyklu życia stanu i jak nim zarządzać. +Przeczytaj rozdział pt. **[Zachowywanie i resetowanie stanu](/learn/preserving-and-resetting-state)**, aby nauczyć się cyklu życia stanu i jak nim zarządzać. diff --git a/src/content/learn/preserving-and-resetting-state.md b/src/content/learn/preserving-and-resetting-state.md index 0a884d46a..d47dcfe04 100644 --- a/src/content/learn/preserving-and-resetting-state.md +++ b/src/content/learn/preserving-and-resetting-state.md @@ -1,28 +1,28 @@ --- -title: Utrzymywanie i resetowanie stanu +title: Zachowywanie i resetowanie stanu --- -State is isolated between components. React keeps track of which state belongs to which component based on their place in the UI tree. You can control when to preserve state and when to reset it between re-renders. +Stan jest izolowany między komponentami. React śledzi, który stan należy do którego komponentu na podstawie ich miejsca w drzewie interfejsu użytkownika. Możesz kontrolować, kiedy zachować stan, a kiedy go zresetować między renderowaniami. -* When React chooses to preserve or reset the state -* How to force React to reset component's state -* How keys and types affect whether the state is preserved +* Kiedy React decyduje, aby zachować lub zresetować stan +* Jak zmusić React do zresetowania stanu komponentu +* Jak klucze i typy wpływają na to, czy stan jest zachowany -## State is tied to a position in the render tree {/*state-is-tied-to-a-position-in-the-tree*/} +## Stan jest powiązany z pozycją w drzewie renderowania {/*state-is-tied-to-a-position-in-the-tree*/} -React builds [render trees](learn/understanding-your-ui-as-a-tree#the-render-tree) for the component structure in your UI. +React buduje [drzewa renderowania](learn/understanding-your-ui-as-a-tree#the-render-tree) dla struktury komponentów w twoim interfejsie użytkownika. -When you give a component state, you might think the state "lives" inside the component. But the state is actually held inside React. React associates each piece of state it's holding with the correct component by where that component sits in the render tree. +Kiedy dodajesz stan do komponentu, możesz myśleć, że stan "żyje" wewnątrz komponentu. Jednak w rzeczywistości jest on przechowywany wewnątrz Reacta. Kojarzy on każdą część stanu, którą przechowuje, z odpowiednim komponentem na podstawie jego miejsca w drzewie renderowania. -Here, there is only one `` JSX tag, but it's rendered at two different positions: +W poniższym przykładzie, jest tylko jeden tag `` w składni JSX, ale jest renderowany na dwóch różnych pozycjach: @@ -56,7 +56,7 @@ function Counter() { >

{score}

); @@ -86,23 +86,23 @@ label {
-Here's how these look as a tree: +Oto jak te komponenty wyglądają jako drzewo: - + -React tree +Drzewo Reacta -**These are two separate counters because each is rendered at its own position in the tree.** You don't usually have to think about these positions to use React, but it can be useful to understand how it works. +**To są dwa oddzielne liczniki, ponieważ każdy jest renderowany na swojej własnej pozycji w drzewie.** Zazwyczaj nie musisz myśleć o tych pozycjach, aby korzystać z Reacta, ale zrozumienie zasady działania może okazać się przydatne. -In React, each component on the screen has fully isolated state. For example, if you render two `Counter` components side by side, each of them will get its own, independent, `score` and `hover` states. +W Reakcie, każdy komponent na ekranie ma całkowicie izolowany stan. Na przykład, jeśli renderujesz dwa komponenty `Counter` obok siebie, każdy z nich będzie miał swoje własne, niezależne stany `score` i `hover`. -Try clicking both counters and notice they don't affect each other: +Spróbuj klikać oba liczniki i zauważ, że nie wpływają one na siebie nawzajem: @@ -135,7 +135,7 @@ function Counter() { >

{score}

); @@ -160,21 +160,21 @@ function Counter() {
-As you can see, when one counter is updated, only the state for that component is updated: +Jak widać, gdy jeden licznik jest aktualizowany, tylko stan dla tego komponentu jest aktualizowany: - + -Updating state +Aktualizacja stanu -React will keep the state around for as long as you render the same component at the same position in the tree. To see this, increment both counters, then remove the second component by unchecking "Render the second counter" checkbox, and then add it back by ticking it again: +React będzie przechowywać stan tak długo, jak długo renderujesz ten sam komponent na tej samej pozycji w drzewie. Aby to zaobserwować, zwiększ oba liczniki, a następnie usuń drugi komponent, odznaczając pole wyboru "Renderuj drugi licznik", a potem dodaj go z powrotem, zaznaczając je ponownie: @@ -195,7 +195,7 @@ export default function App() { setShowB(e.target.checked) }} /> - Render the second counter + Renderuj drugi licznik ); @@ -218,7 +218,7 @@ function Counter() { >

{score}

); @@ -248,35 +248,35 @@ label {
-Notice how the moment you stop rendering the second counter, its state disappears completely. That's because when React removes a component, it destroys its state. +Zauważ, że w momencie, gdy przestajesz renderować drugi licznik, jego stan znika całkowicie. Dzieje się tak, ponieważ kiedy React usuwa komponent, niszczy też jego stan. - + -Deleting a component +Usuwanie komponentu -When you tick "Render the second counter", a second `Counter` and its state are initialized from scratch (`score = 0`) and added to the DOM. +Kiedy zaznaczasz pole wyboru "Renderuj drugi licznik", drugi komponent `Counter` i jego stan są inicjalizowane od nowa (`score = 0`) i dodawane do drzewa DOM. - + -Adding a component +Dodawanie komponentu -**React preserves a component's state for as long as it's being rendered at its position in the UI tree.** If it gets removed, or a different component gets rendered at the same position, React discards its state. +**React zachowuje stan komponentu tak długo, jak jest on renderowany na swojej pozycji w drzewie UI.** Jeśli zostanie on usunięty lub na jego miejsce zostanie wyrenderowany inny komponent, React odrzuci jego stan. -## Same component at the same position preserves state {/*same-component-at-the-same-position-preserves-state*/} +## Ten sam komponent na tej samej pozycji zachowuje stan {/*same-component-at-the-same-position-preserves-state*/} -In this example, there are two different `` tags: +W tym przykładzie znajdują się dwa różne tagi ``: @@ -300,7 +300,7 @@ export default function App() { setIsFancy(e.target.checked) }} /> - Use fancy styling + Użyj wyszukanego stylu ); @@ -326,7 +326,7 @@ function Counter({ isFancy }) { >

{score}

); @@ -361,24 +361,24 @@ label {
-When you tick or clear the checkbox, the counter state does not get reset. Whether `isFancy` is `true` or `false`, you always have a `` as the first child of the `div` returned from the root `App` component: +Gdy zaznaczysz lub odznaczysz pole wyboru, stan licznika nie jest resetowany. Niezależnie od tego, czy `isFancy` jest ustawione na `true`, czy `false`, komponent `` jest zawsze pierwszym potomkiem elementu `div` zwracanego z głównego komponentu `App` - + -Updating the `App` state does not reset the `Counter` because `Counter` stays in the same position +Aktualizacja stanu `App` nie resetuje `Counter`, ponieważ `Counter` pozostaje na tej samej pozycji -It's the same component at the same position, so from React's perspective, it's the same counter. +To ten sam komponent na tej samej pozycji, więc z perspektywy Reacta to jest ten sam licznik. -Remember that **it's the position in the UI tree--not in the JSX markup--that matters to React!** This component has two `return` clauses with different `` JSX tags inside and outside the `if`: +Pamiętaj, że to pozycja w drzewie UI — a nie w kodzie JSX — ma znaczenie dla Reacta! Ten komponent ma dwa wyrażenia `return` z różnymi tagami `` wewnątrz i na zewnątrz instrukcji if: @@ -399,7 +399,7 @@ export default function App() { setIsFancy(e.target.checked) }} /> - Use fancy styling + Użyj wyszukanego stylu ); @@ -415,7 +415,7 @@ export default function App() { setIsFancy(e.target.checked) }} /> - Use fancy styling + Użyj wyszukanego stylu ); @@ -441,7 +441,7 @@ function Counter({ isFancy }) { >

{score}

); @@ -476,15 +476,15 @@ label {
-You might expect the state to reset when you tick checkbox, but it doesn't! This is because **both of these `` tags are rendered at the same position.** React doesn't know where you place the conditions in your function. All it "sees" is the tree you return. +Możesz oczekiwać, że stan zostanie zresetowany, gdy zaznaczysz pole wyboru, ale tak się nie stanie! Dzieje się tak, ponieważ **oba tagi `` są renderowane na tej samej pozycji.** React nie wie, gdzie umieszczasz warunki w swojej funkcji. Wszystko, co „widzi”, to drzewo, które zwracasz. -In both cases, the `App` component returns a `
` with `` as a first child. To React, these two counters have the same "address": the first child of the first child of the root. This is how React matches them up between the previous and next renders, regardless of how you structure your logic. +W obu przypadkach komponent `App` zwraca element `
` z komponentem `` jako pierwszym potomkiem. Dla Reacta te dwa liczniki mają ten sam „adres”: pierwszy potomek pierwszego potomka głównego węzła. W taki sposób React łączy je między poprzednimi a kolejnymi renderowaniami, niezależnie od tego, jaką strukturę ma twoja logika. -## Different components at the same position reset state {/*different-components-at-the-same-position-reset-state*/} +## Różne komponenty na tej samej pozycji resetują stan {/*different-components-at-the-same-position-reset-state*/} -In this example, ticking the checkbox will replace `` with a `

`: +W tym przykładzie zaznaczenie pola wyboru zastąpi komponent `` elementem `

`: @@ -496,7 +496,7 @@ export default function App() { return (

{isPaused ? ( -

See you later!

+

Do zobaczenia później!

) : ( )} @@ -508,7 +508,7 @@ export default function App() { setIsPaused(e.target.checked) }} /> - Take a break + Zrób przerwę
); @@ -531,7 +531,7 @@ function Counter() { >

{score}

); @@ -561,13 +561,13 @@ label { -Here, you switch between _different_ component types at the same position. Initially, the first child of the `
` contained a `Counter`. But when you swapped in a `p`, React removed the `Counter` from the UI tree and destroyed its state. +Tutaj przełączasz się między _różnymi_ typami komponentów na tej samej pozycji. Początkowo, pierwszy potomek `
` zawierał komponent `Counter`. Jednak kiedy zamieniono go na `p`, React usunął komponent `Counter` z drzewa UI i zniszczył jego stan. - + -When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added +Gdy komponent `Counter` zmienia się na element `p`, `Counter` zostaje usunięty, a `p` zostaje dodany. @@ -575,15 +575,15 @@ When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added - + -When switching back, the `p` is deleted and the `Counter` is added +Kiedy przełączasz z powrotem, `p` jest usuwany, a `Counter` jest dodawany -Also, **when you render a different component in the same position, it resets the state of its entire subtree.** To see how this works, increment the counter and then tick the checkbox: +Również **renderowanie innego komponentu na tej samej pozycji resetuje stan całego jego poddrzewa.** Aby zobaczyć, jak to działa, zwiększ licznik, a następnie zaznacz pole wyboru: @@ -611,7 +611,7 @@ export default function App() { setIsFancy(e.target.checked) }} /> - Use fancy styling + Użyj wyszukanego stylu
); @@ -637,7 +637,7 @@ function Counter({ isFancy }) { >

{score}

); @@ -672,13 +672,13 @@ label { -The counter state gets reset when you click the checkbox. Although you render a `Counter`, the first child of the `div` changes from a `div` to a `section`. When the child `div` was removed from the DOM, the whole tree below it (including the `Counter` and its state) was destroyed as well. +Stan licznika zostaje zresetowany, gdy klikniesz pole wyboru. Chociaż renderujesz komponent `Counter`, pierwszy potomek elementu `div` zmienia się z `div` na `section`. Kiedy potomek `div` został usunięty z drzewa DOM, całe drzewo poniżej niego (w tym komponent `Counter` i jego stan) zostało również zniszczone. - + -When `section` changes to `div`, the `section` is deleted and the new `div` is added +Gdy element `section` zmienia się na `div`, `section` zostaje usunięty, a nowy `div` zostaje dodany. @@ -686,21 +686,21 @@ When `section` changes to `div`, the `section` is deleted and the new `div` is a - + -When switching back, the `div` is deleted and the new `section` is added +Gdy następuje odwrotna sytuacja, `div` zostaje usunięty, a nowy element `section` zostaje dodany. -As a rule of thumb, **if you want to preserve the state between re-renders, the structure of your tree needs to "match up"** from one render to another. If the structure is different, the state gets destroyed because React destroys state when it removes a component from the tree. +Ogólna zasada jest taka, że **jeśli chcesz zachować stan pomiędzy renderowaniami, struktura drzewa musi "pasować"** między jednym a drugim renderowaniem. Jeśli struktura jest inna, stan zostaje zniszczony, ponieważ React usuwa stan, gdy usuwa komponent z drzewa. -This is why you should not nest component function definitions. +Oto dlaczego nie powinno się zagnieżdżać definicji funkcji komponentów. -Here, the `MyTextField` component function is defined *inside* `MyComponent`: +Tutaj funkcja komponentu `MyTextField` jest zdefiniowana *wewnątrz* komponentu `MyComponent`: @@ -726,7 +726,7 @@ export default function MyComponent() { + }}>Naciśnięto {counter} razy ); } @@ -735,13 +735,13 @@ export default function MyComponent() { -Every time you click the button, the input state disappears! This is because a *different* `MyTextField` function is created for every render of `MyComponent`. You're rendering a *different* component in the same position, so React resets all state below. This leads to bugs and performance problems. To avoid this problem, **always declare component functions at the top level, and don't nest their definitions.** +Za każdym razem, gdy klikasz przycisk, stan pola wejściowego znika! Dzieje się tak, ponieważ za każdym razem, gdy renderowany jest komponent `MyComponent`, tworzona jest *inna* funkcja `MyTextField`. Renderujesz *inny* komponent na tej samej pozycji, więc React resetuje cały stan poniżej. Prowadzi to do błędów i problemów z wydajnością. Aby uniknąć tego problemu, **zawsze deklaruj funkcje komponentów na najwyższym poziomie i nie zagnieżdżaj ich definicji.** -## Resetting state at the same position {/*resetting-state-at-the-same-position*/} +## Resetowanie stanu na tej samej pozycji {/*resetting-state-at-the-same-position*/} -By default, React preserves state of a component while it stays at the same position. Usually, this is exactly what you want, so it makes sense as the default behavior. But sometimes, you may want to reset a component's state. Consider this app that lets two players keep track of their scores during each turn: +Domyślnie React zachowuje stan komponentu, dopóki pozostaje on na tej samej pozycji. Zazwyczaj jest to dokładnie to, czego oczekujesz, więc to domyślne zachowanie ma sens. Czasami jednak możesz chcieć zresetować stan komponentu. Rozważ poniższą aplikację, która pozwala dwóm graczom śledzić swoje wyniki podczas każdej tury: @@ -760,7 +760,7 @@ export default function Scoreboard() {
); @@ -781,9 +781,9 @@ function Counter({ person }) { onPointerEnter={() => setHover(true)} onPointerLeave={() => setHover(false)} > -

{person}'s score: {score}

+

Wynik gracza {person}: {score}

); @@ -811,19 +811,19 @@ h1 { -Currently, when you change the player, the score is preserved. The two `Counter`s appear in the same position, so React sees them as *the same* `Counter` whose `person` prop has changed. +Obecnie, gdy zmieniasz gracza, wynik jest zachowany. Dwa komponenty licznika `Counter` pojawiają się na tej samej pozycji, więc React widzi je jako *ten sam* komponent `Counter`, w którym zmieniła się właściwość `person`. -But conceptually, in this app they should be two separate counters. They might appear in the same place in the UI, but one is a counter for Taylor, and another is a counter for Sarah. +Ale w tym przypadku, koncepcyjnie powinny to być dwa osobne liczniki. Mogą pojawiać się w tym samym miejscu w interfejsie użytkownika, ale jeden z nich to licznik dla Taylora, a drugi dla Sarah. -There are two ways to reset state when switching between them: +Istnieją dwa sposoby na zresetowanie stanu podczas przełączania się między licznikami: -1. Render components in different positions -2. Give each component an explicit identity with `key` +1. Renderowanie komponentów na różnych pozycjach +2. Nadanie każdemu komponentowi konkretnej tożsamości za pomocą klucza `key` -### Option 1: Rendering a component in different positions {/*option-1-rendering-a-component-in-different-positions*/} +### Opcja 1: Renderowanie komponentu na różnych pozycjach {/*option-1-rendering-a-component-in-different-positions*/} -If you want these two `Counter`s to be independent, you can render them in two different positions: +Jeśli chcesz, aby te dwa komponenty `Counter` były niezależne, możesz wyrenderować je na dwóch różnych pozycjach: @@ -843,7 +843,7 @@ export default function Scoreboard() { ); @@ -864,9 +864,9 @@ function Counter({ person }) { onPointerEnter={() => setHover(true)} onPointerLeave={() => setHover(false)} > -

{person}'s score: {score}

+

Wynik gracza {person}: {score}

); @@ -894,42 +894,42 @@ h1 {
-* Initially, `isPlayerA` is `true`. So the first position contains `Counter` state, and the second one is empty. -* When you click the "Next player" button the first position clears but the second one now contains a `Counter`. +* Początkowo, `isPlayerA` ma wartość `true`. W związku z tym pierwsza pozycja zawiera komponent `Counter`, a druga jest pusta. +* Kiedy klikniesz przycisk "Następny gracz", pierwsza pozycja się opróżnia, a w drugiej pojawia się komponent `Counter`. - + -Initial state +Stan początkowy - + -Clicking "next" +Kliknięcie "następny" - + -Clicking "next" again +Kliknięcie "następny" ponownie -Each `Counter`'s state gets destroyed each time it's removed from the DOM. This is why they reset every time you click the button. +Stan każdego komponentu `Counter` jest niszczony za każdym razem, gdy jest usuwany z drzewa DOM. To dlatego stany te resetują się za każdym razem, gdy klikniesz przycisk. -This solution is convenient when you only have a few independent components rendered in the same place. In this example, you only have two, so it's not a hassle to render both separately in the JSX. +To rozwiązanie jest wygodne, gdy masz tylko kilka niezależnych komponentów renderowanych w tym samym miejscu. W tym przykładzie są tylko dwa, więc nie ma problemu z renderowaniem obu osobno w składni JSX. -### Option 2: Resetting state with a key {/*option-2-resetting-state-with-a-key*/} +### Opcja 2: Resetowanie stanu za pomocą klucza (ang. _key_) {/*option-2-resetting-state-with-a-key*/} -There is also another, more generic, way to reset a component's state. +Istnieje także inny, bardziej ogólny sposób na zresetowanie stanu komponentu. -You might have seen `key`s when [rendering lists.](/learn/rendering-lists#keeping-list-items-in-order-with-key) Keys aren't just for lists! You can use keys to make React distinguish between any components. By default, React uses order within the parent ("first counter", "second counter") to discern between components. But keys let you tell React that this is not just a *first* counter, or a *second* counter, but a specific counter--for example, *Taylor's* counter. This way, React will know *Taylor's* counter wherever it appears in the tree! +Przy [renderowaniu list](/learn/rendering-lists#keeping-list-items-in-order-with-key) można zauważyć użycie kluczy. Klucze te nie są tylko dla list! Możesz użyć kluczy, aby pomóc Reactowi rozróżnić dowolne komponenty. Domyślnie React używa kolejności w obrębie rodzica ("pierwszy licznik", "drugi licznik"), aby odróżnić komponenty. Jednak klucze pozwalają powiedzieć Reactowi, że to nie jest tylko *pierwszy* licznik czy *drugi* licznik, ale jakiś konkretny licznik - na przykład *licznik Taylora*. W ten sposób React będzie wiedział, że to licznik *Taylora*, niezależnie od tego, gdzie pojawi się on w drzewie! -In this example, the two ``s don't share state even though they appear in the same place in JSX: +W tym przykładzie dwa komponenty `` nie dzielą stanu, mimo że pojawiają się w tym samym miejscu w składni JSX: @@ -948,7 +948,7 @@ export default function Scoreboard() { ); @@ -969,9 +969,9 @@ function Counter({ person }) { onPointerEnter={() => setHover(true)} onPointerLeave={() => setHover(false)} > -

{person}'s score: {score}

+

Wynika gracza {person}: {score}

); @@ -999,7 +999,7 @@ h1 {
-Switching between Taylor and Sarah does not preserve the state. This is because **you gave them different `key`s:** +Przełączanie między graczami Taylor a Sarah nie zachowuje ich stanu. Dzieje się tak, ponieważ **przypisano im różne klucze `key`**: ```js {isPlayerA ? ( @@ -1009,19 +1009,19 @@ Switching between Taylor and Sarah does not preserve the state. This is because )} ``` -Specifying a `key` tells React to use the `key` itself as part of the position, instead of their order within the parent. This is why, even though you render them in the same place in JSX, React sees them as two different counters, and so they will never share state. Every time a counter appears on the screen, its state is created. Every time it is removed, its state is destroyed. Toggling between them resets their state over and over. +Określenie klucza `key` mówi Reactowi, aby użył jego samego jako części pozycji, zamiast polegać na kolejności w obrębie rodzica. Dlatego, chociaż renderujesz je w tym samym miejscu w składni JSX, React postrzega je jako dwa różne liczniki, więc nigdy nie będą one dzielić stanu. Za każdym razem, gdy licznik pojawia się na ekranie, jego stan jest tworzony. Za każdym razem, gdy jest usuwany, jego stan jest niszczony. Przełączanie między komponentami resetuje ich stan w kółko. -Remember that keys are not globally unique. They only specify the position *within the parent*. +Pamiętaj, że klucze nie są unikalne globalnie. Określają one pozycję tylko *w obrębie rodzica*. -### Resetting a form with a key {/*resetting-a-form-with-a-key*/} +### Resetowanie formularza za pomocą klucza {/*resetting-a-form-with-a-key*/} -Resetting state with a key is particularly useful when dealing with forms. +Resetowanie stanu za pomocą klucza jest szczególnie przydatne podczas pracy z formularzami. -In this chat app, the `` component contains the text input state: +W poniższej aplikacji czatu, komponent `` zawiera stan dla pola tekstowego: @@ -1084,11 +1084,11 @@ export default function Chat({ contact }) {