From 7bf5c3dd4c8f50b760ef88ddc59d04d8868c75db Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Sat, 19 Aug 2023 15:31:10 +0200 Subject: [PATCH 01/14] Part 1 - til "Should you add useCallback everywhere?" --- src/content/reference/react/useCallback.md | 91 +++++++++++----------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 63b36a600..aa2c622eb 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -4,7 +4,7 @@ title: useCallback -`useCallback` is a React Hook that lets you cache a function definition between re-renders. +`useCallback` jest hookiem reactowym, który pozwala na zapamiętywanie (ang. cache) definicji funkcji pomiędzy przerenderowaniami. ```js const cachedFn = useCallback(fn, dependencies) @@ -16,11 +16,11 @@ const cachedFn = useCallback(fn, dependencies) --- -## Reference {/*reference*/} +## Dokumentacja {/*reference*/} ### `useCallback(fn, dependencies)` {/*usecallback*/} -Call `useCallback` at the top level of your component to cache a function definition between re-renders: +Wywołaj `useCallback` na głównym poziomie komponentu, aby zapamiętać definicje funkcji pomiędzy przerenderowaniami: ```js {4,9} import { useCallback } from 'react'; @@ -34,34 +34,34 @@ export default function ProductPage({ productId, referrer, theme }) { }, [productId, referrer]); ``` -[See more examples below.](#usage) +[Więcej przykładów znajdziesz poniżej.](#usage) -#### Parameters {/*parameters*/} +#### Parametry {/*parameters*/} -* `fn`: The function value that you want to cache. It can take any arguments and return any values. React will return (not call!) your function back to you during the initial render. On next renders, React will give you the same function again if the `dependencies` have not changed since the last render. Otherwise, it will give you the function that you have passed during the current render, and store it in case it can be reused later. React will not call your function. The function is returned to you so you can decide when and whether to call it. +* `fn`: Funkcja, którą chcesz zapamiętać. Może przyjąć dowolne argumenty i zwrócić dowolne wartości. React zwróci (nie wywoła!) twoją funkcję z powrotem w pierwszym renderowaniu. Przy kolejnych renderowaniach, React zwróci ci tę samą funkcję ponownie jeśli lista zależności `dependencies` nie zmieni się od ostatniego renderowania. W przeciwnym razie zwróci ci funkcję, którą przekazałeś podczas obecnego renderowania i zachowa ją do ponownego użycia potem. React nie wywoła twojej funkcji. Funkcja ta zostanie ci zwrócona, abyś mógł sam wybrać gdzie i kiedy ma być wywołana. -* `dependencies`: The list of all reactive values referenced inside of the `fn` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison algorithm. +* `dependencies`: Lista wszystkich reaktywnych (?) wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała (?) komponentu. Jeżeli twój linter jest [skonfigurowany dla Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost (?) jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). -#### Returns {/*returns*/} +#### Zwracan wartość {/*returns*/} -On the initial render, `useCallback` returns the `fn` function you have passed. +Podczas pierwszego renderowania, `useCallback` zwróci funkcję `fn` którą przekazałeś. -During subsequent renders, it will either return an already stored `fn` function from the last render (if the dependencies haven't changed), or return the `fn` function you have passed during this render. +Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z poprzedniego renderowania (jeśli zależności nie uległy zmianie) albo zwróci funkcję `fn`, którą przekazałeś podczas tego renderowania. -#### Caveats {/*caveats*/} +#### Zastrzeżenia {/*caveats*/} -* `useCallback` is a Hook, so you can only call it **at the top level of your component** or your own Hooks. You can't call it inside loops or conditions. If you need that, extract a new component and move the state into it. -* React **will not throw away the cached function unless there is a specific reason to do that.** For example, in development, React throws away the cache when you edit the file of your component. Both in development and in production, React will throw away the cache if your component suspends during the initial mount. In the future, React may add more features that take advantage of throwing away the cache--for example, if React adds built-in support for virtualized lists in the future, it would make sense to throw away the cache for items that scroll out of the virtualized table viewport. This should match your expectations if you rely on `useCallback` as a performance optimization. Otherwise, a [state variable](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) or a [ref](/reference/react/useRef#avoiding-recreating-the-ref-contents) may be more appropriate. +* `useCallback` jest hookiem, więc można go wywoływać tylko **na głównym poziomie komponentu** lub innego hooka. Nie można go wywołać w pętli lub instrukcji warunkowej. Jeśli masz sytuację, która wymaga pętli lub warunku, stwórz nowy komponent i przenieś do niego ten stan. +* React **nie odrzuci zapamiętanej funkcji chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania (?). W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar (?) zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. --- -## Usage {/*usage*/} +## Sposób użycia {/*usage*/} -### Skipping re-rendering of components {/*skipping-re-rendering-of-components*/} +### Pomijanie przerenderowywania komponentów {/*skipping-re-rendering-of-components*/} -When you optimize rendering performance, you will sometimes need to cache the functions that you pass to child components. Let's first look at the syntax for how to do this, and then see in which cases it's useful. +Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do potomków komponentów. Spójrzmy najpierw na składnię jak to zrobić, a potem w jakich przypadkach jest to przydatne. -To cache a function between re-renders of your component, wrap its definition into the `useCallback` Hook: +Aby zapamiętać funkcję pomiędzy renderowaniami twojego komponentu, zawrzyj jej definicję w hooku `useCallback`: ```js [[3, 4, "handleSubmit"], [2, 9, "[productId, referrer]"]] import { useCallback } from 'react'; @@ -76,20 +76,20 @@ function ProductPage({ productId, referrer, theme }) { // ... ``` -You need to pass two things to `useCallback`: +Musisz przekazać dwie rzeczy do `useCallback`: -1. A function definition that you want to cache between re-renders. -2. A list of dependencies including every value within your component that's used inside your function. +1. Definicję funkcji, którą chcesz zapamiętać pomiędzy przerenderowaniami. +2. Listę zależności zawierającą wszystkie wartości wewnątrz komponentu, które są użyte w twojej funkcji. -On the initial render, the returned function you'll get from `useCallback` will be the function you passed. +Przy pierwszym renderowaniu, zwrócona funkcja otrzymana z `useCallback` będzie tą samą, którą przekazałeś. -On the following renders, React will compare the dependencies with the dependencies you passed during the previous render. If none of the dependencies have changed (compared with [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), `useCallback` will return the same function as before. Otherwise, `useCallback` will return the function you passed on *this* render. +Przy następnych renderowaniach, React porówna zależności z zależnościami, które przekazałeś w poprzednim renderowaniu. Jeśli żadna z zależności nie uległa zmianie (porównując z użyciem [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), `useCallback` zwróci tę samą funkcję co poprzednio. W innym wypadku, `useCallback` zwróci funkcję, którą przekazałeś w *tym* renderowaniu. -In other words, `useCallback` caches a function between re-renders until its dependencies change. +Innymi słowy, `useCallback` zapamięta funkcję pomiędzy przerenderowaniami dopóki zależności się nie zmienią. -**Let's walk through an example to see when this is useful.** +**Posłużmy się przykładem aby zobaczyć kiedy to może być przydatne.** -Say you're passing a `handleSubmit` function down from the `ProductPage` to the `ShippingForm` component: +Załóżmy, że przekazujesz funkcję `handleSubmit` w dół z `ProductPage` do komponentu `ShippingForm`: ```js {5} function ProductPage({ productId, referrer, theme }) { @@ -102,8 +102,12 @@ function ProductPage({ productId, referrer, theme }) { ``` You've noticed that toggling the `theme` prop freezes the app for a moment, but if you remove `` from your JSX, it feels fast. This tells you that it's worth trying to optimize the `ShippingForm` component. +Zauważyłeś, że zmienianie właściwości `theme` zatrzymuje na chwilę aplikację, ale gdy usuniesz `` from twojego JSX, zauważysz, że znów działa szybko. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. **By default, when a component re-renders, React re-renders all of its children recursively.** This is why, when `ProductPage` re-renders with a different `theme`, the `ShippingForm` component *also* re-renders. This is fine for components that don't require much calculation to re-render. But if you verified a re-render is slow, you can tell `ShippingForm` to skip re-rendering when its props are the same as on last render by wrapping it in [`memo`:](/reference/react/memo) +**Domyślnie, kiedy komponent się przerenderowuje, React przerenderowuje rekurencyjnie wszystkie jego elementy potomne.** To dlatego gdy `ProductPage` przerenderowu + +**Domyślnie, gdy komponent zostaje ponownie przerenderowany, React przerenderowuje rekursywnie wszystkie jego elementy potomne.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. To jest w porządku dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli sprawdziłeś, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowywania, owijając (?) go w [`memo`:](/reference/react/memo) ```js {3,5} import { memo } from 'react'; @@ -113,11 +117,10 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { }); ``` -**With this change, `ShippingForm` will skip re-rendering if all of its props are the *same* as on the last render.** This is when caching a function becomes important! Let's say you defined `handleSubmit` without `useCallback`: +**Po dokonaniu tej zmiany, komponent `ShippingForm` pominie przerenderowanie, jeśli wszystkie jego właściwości są *takie same* jak podczas ostatniego renderowania.** To jest moment, w którym istotne staje się zapamitywanie (?) funkcji! Załóżmy, że zdefiniowałeś funkcję `handleSubmit` bez użycia hooka `useCallback`: ```js {2,3,8,12-13} function ProductPage({ productId, referrer, theme }) { - // Every time the theme changes, this will be a different function... function handleSubmit(orderDetails) { post('/product/' + productId + '/buy', { referrer, @@ -127,47 +130,47 @@ function ProductPage({ productId, referrer, theme }) { return (
- {/* ... so ShippingForm's props will never be the same, and it will re-render every time */} + {/* ... więc właściwości ShippingForm nigdy nie będą takie same i komponent ten przerenderuje się za każdym razem */}
); } ``` -**In JavaScript, a `function () {}` or `() => {}` always creates a _different_ function,** similar to how the `{}` object literal always creates a new object. Normally, this wouldn't be a problem, but it means that `ShippingForm` props will never be the same, and your [`memo`](/reference/react/memo) optimization won't work. This is where `useCallback` comes in handy: +**W języku JavaScript, `function () {}` lub `() => {}` zawsze tworzy _inną_ funkcję,** podobnie jak literał obiektu `{}` zawsze tworzy nowy obiekt. Zazwyczaj nie byłoby to problemem, ale oznacza to, że właściwości komponentu `ShippingForm` nigdy nie będą takie same, i optymalizacja [`memo`](/reference/react/memo) nie zadziała. Tutaj przydaje się `useCallback`: ```js {2,3,8,12-13} function ProductPage({ productId, referrer, theme }) { - // Tell React to cache your function between re-renders... + // Powiedz Reactowi, aby zapamiętał Twoją funkcję między przerenderowaniami... const handleSubmit = useCallback((orderDetails) => { post('/product/' + productId + '/buy', { referrer, orderDetails, }); - }, [productId, referrer]); // ...so as long as these dependencies don't change... + }, [productId, referrer]); // ... dopóki te zależności się nie zmienią... return (
- {/* ...ShippingForm will receive the same props and can skip re-rendering */} + {/* ...ShippingForm otrzyma te same elementy potomne i może pominąć przerenderowanie */}
); } ``` -**By wrapping `handleSubmit` in `useCallback`, you ensure that it's the *same* function between the re-renders** (until dependencies change). You don't *have to* wrap a function in `useCallback` unless you do it for some specific reason. In this example, the reason is that you pass it to a component wrapped in [`memo`,](/reference/react/memo) and this lets it skip re-rendering. There are other reasons you might need `useCallback` which are described further on this page. +**Owrapowanie (?) `handleSubmit` w `useCallback` zapewnia, że to jest ta *sama* funkcja między przerenderowaniami** (aż do zmiany zależności). Nie *musisz* opakowywać funkcji w `useCallback`, chyba że robisz to z jakiegoś konkretnego powodu. W tym przykładzie powodem jest to, że przekazujesz ją do komponentu owrapowanego (?) w [`memo`,](/reference/react/memo) co pozwala na pominięcie przerenderowania. Istnieją inne powody, dla których możesz potrzebować `useCallback`, opisane dalej na tej stronie. -**You should only rely on `useCallback` as a performance optimization.** If your code doesn't work without it, find the underlying problem and fix it first. Then you may add `useCallback` back. +**Powinieneś polegać na `useCallback` tylko jako optymalizacji wydajnościowej.** Jeśli twój kod nie działa bez niego, najpierw znajdź prawdziwą przyczynę problemu i napraw ją. Następnie możesz ponownie dodać `useCallback`. -#### How is useCallback related to useMemo? {/*how-is-usecallback-related-to-usememo*/} +#### Jaki jest związek między useCallback a useMemo? {/*how-is-usecallback-related-to-usememo*/} -You will often see [`useMemo`](/reference/react/useMemo) alongside `useCallback`. They are both useful when you're trying to optimize a child component. They let you [memoize](https://en.wikipedia.org/wiki/Memoization) (or, in other words, cache) something you're passing down: +Często zobaczysz [`useMemo`](/reference/react/useMemo) obok `useCallback`. Oba są przydatne, gdy próbujesz zoptymalizować komponent potomny. Pozwalają one na [memoizację](https://pl.wikipedia.org/wiki/Memoization) (lub inaczej mówiąc, buforowanie (?)) tego, co przekazujesz w dół: ```js {6-8,10-15,19} import { useMemo, useCallback } from 'react'; @@ -175,11 +178,11 @@ import { useMemo, useCallback } from 'react'; function ProductPage({ productId, referrer }) { const product = useData('/product/' + productId); - const requirements = useMemo(() => { // Calls your function and caches its result + const requirements = useMemo(() => { // Wywołuje twoją funkcję i zapamiętuje jej wynik return computeRequirements(product); }, [product]); - const handleSubmit = useCallback((orderDetails) => { // Caches your function itself + const handleSubmit = useCallback((orderDetails) => { // Zapamiętuje samą twoją funkcję post('/product/' + productId + '/buy', { referrer, orderDetails, @@ -194,21 +197,21 @@ function ProductPage({ productId, referrer }) { } ``` -The difference is in *what* they're letting you cache: +Różnica polega na tym *co* pozwalają ci buforować (?): -* **[`useMemo`](/reference/react/useMemo) caches the *result* of calling your function.** In this example, it caches the result of calling `computeRequirements(product)` so that it doesn't change unless `product` has changed. This lets you pass the `requirements` object down without unnecessarily re-rendering `ShippingForm`. When necessary, React will call the function you've passed during rendering to calculate the result. -* **`useCallback` caches *the function itself.*** Unlike `useMemo`, it does not call the function you provide. Instead, it caches the function you provided so that `handleSubmit` *itself* doesn't change unless `productId` or `referrer` has changed. This lets you pass the `handleSubmit` function down without unnecessarily re-rendering `ShippingForm`. Your code won't run until the user submits the form. +* **[`useMemo`](/reference/react/useMemo) buforuje (?) *wynik* wywołania Twojej funkcji.** W tym przykładzie buforuje wynik wywołania `computeRequirements(product)`, aby nie zmieniał się, chyba że zmieni się `product`. Pozwala to przekazywać obiekt `requirements` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Gdy będzie to konieczne, React wywoła funkcję, którą przekazałeś podczas renderowania, aby obliczyć wynik. +* **`useCallback` buforuje *samą funkcję*.** W przeciwieństwie do `useMemo`, nie wywołuje dostarczonej funkcji. Zamiast tego buforuje funkcję, którą podałeś, tak aby `handleSubmit` *sam* nie zmieniał się, chyba że zmieni się `productId` lub `referrer`. Pozwala to przekazywać funkcję `handleSubmit` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Twój kod nie zostanie uruchomiony, dopóki użytkownik nie prześle formularza. -If you're already familiar with [`useMemo`,](/reference/react/useMemo) you might find it helpful to think of `useCallback` as this: +Jeśli już jesteś zaznajomiony z [`useMemo`,](/reference/react/useMemo) pomocne może być myślenie o `useCallback` w ten sposób: ```js -// Simplified implementation (inside React) +// Uproszczona implementacja (wewnątrz Reacta) function useCallback(fn, dependencies) { return useMemo(() => fn, dependencies); } ``` -[Read more about the difference between `useMemo` and `useCallback`.](/reference/react/useMemo#memoizing-a-function) +[Przeczytaj więcej o różnicy między `useMemo` a `useCallback`.](/reference/react/useMemo#memoizing-a-function) From c4fe9c8565578629be45f143aa3ab84d8c4244f6 Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Sat, 19 Aug 2023 16:25:45 +0200 Subject: [PATCH 02/14] Part 2 - til "updating-state-from-a-memoized-callback" --- src/content/reference/react/useCallback.md | 98 +++++++++++----------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index aa2c622eb..fb55c2560 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -217,40 +217,40 @@ function useCallback(fn, dependencies) { -#### Should you add useCallback everywhere? {/*should-you-add-usecallback-everywhere*/} +#### Czy powinieneś używać useCallback wszędzie? {/*should-you-add-usecallback-everywhere*/} -If your app is like this site, and most interactions are coarse (like replacing a page or an entire section), memoization is usually unnecessary. On the other hand, if your app is more like a drawing editor, and most interactions are granular (like moving shapes), then you might find memoization very helpful. +Jeśli twoja aplikacja jest podobna do tej strony i większość interakcji jest prostych (takich jak zastępowanie strony lub całej sekcji), to zazwyczaj memoizacja nie jest konieczna. Z drugiej strony, jeśli twoja aplikacja przypomina edytor rysunków i większość interakcji jest dość szczegółowa (takie jak przesuwanie kształtów), to możliwe, że memoizacja będzie bardzo pomocna. -Caching a function with `useCallback` is only valuable in a few cases: +Buforowanie funkcji za pomocą `useCallback` ma wartość tylko w kilku przypadkach: -- You pass it as a prop to a component wrapped in [`memo`.](/reference/react/memo) You want to skip re-rendering if the value hasn't changed. Memoization lets your component re-render only if dependencies changed. -- The function you're passing is later used as a dependency of some Hook. For example, another function wrapped in `useCallback` depends on it, or you depend on this function from [`useEffect.`](/reference/react/useEffect) +- Przekazujesz ją jako element potomny do komponentu owiniętego w [`memo`.](/reference/react/memo) Chcesz pominąć przerysowywanie, jeśli wartość się nie zmieniła. Memoizacja pozwala komponentowi przerysować się tylko wtedy, gdy zmienią się zależności. +- Funkcja, którą przekazujesz, jest później używana jako zależność pewnego Hooka. Na przykład inna funkcja owinięta w `useCallback` zależy od niej, lub ty zależysz od tej funkcji w [`useEffect.`](/reference/react/useEffect) -There is no benefit to wrapping a function in `useCallback` in other cases. There is no significant harm to doing that either, so some teams choose to not think about individual cases, and memoize as much as possible. The downside is that code becomes less readable. Also, not all memoization is effective: a single value that's "always new" is enough to break memoization for an entire component. +W innych przypadkach nie ma korzyści z owijania funkcji w `useCallback`. Nie ma to również znaczącego wpływu na działanie, więc niektóre zespoły wybierają, by nie zastanawiać się nad indywidualnymi przypadkami i stosować buforowanie tak często, jak to możliwe. Wadą tego podejścia jest jednak to, że kod staje się mniej czytelny. Dodatkowo, nie zawsze memoizacja jest skuteczna: pojedyncza wartość, która "zawsze jest nowa", może wystarczyć, aby zepsuć memoizację dla całego komponentu. -Note that `useCallback` does not prevent *creating* the function. You're always creating a function (and that's fine!), but React ignores it and gives you back a cached function if nothing changed. +Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze tworzysz funkcję (i to jest w porządku!), ale React ją ignoruje i zwraca buforowaną funkcję, jeśli nic się nie zmieniło. -**In practice, you can make a lot of memoization unnecessary by following a few principles:** +**W praktyce możesz uniknąć wielu przypadków memoizacji, stosując kilka zasad:** -1. When a component visually wraps other components, let it [accept JSX as children.](/learn/passing-props-to-a-component#passing-jsx-as-children) Then, if the wrapper component updates its own state, React knows that its children don't need to re-render. -1. Prefer local state and don't [lift state up](/learn/sharing-state-between-components) any further than necessary. Don't keep transient state like forms and whether an item is hovered at the top of your tree or in a global state library. -1. Keep your [rendering logic pure.](/learn/keeping-components-pure) If re-rendering a component causes a problem or produces some noticeable visual artifact, it's a bug in your component! Fix the bug instead of adding memoization. -1. Avoid [unnecessary Effects that update state.](/learn/you-might-not-need-an-effect) Most performance problems in React apps are caused by chains of updates originating from Effects that cause your components to render over and over. -1. Try to [remove unnecessary dependencies from your Effects.](/learn/removing-effect-dependencies) For example, instead of memoization, it's often simpler to move some object or a function inside an Effect or outside the component. +1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent warpujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. +1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj nietrwałego (?) stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w globalnej bibliotece stanu. +1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw błąd zamiast dodawać memoizację. +1. Unikaj [niepotrzebnych Efektów (?), które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w Efektach i prowadzą do wielokrotnego przerenderowania komponentów. +1. Staraj się [usunąć niepotrzebne zależności z Efektów.](/learn/removing-effect-dependencies) Na przykład zamiast memoizacji, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do Efektu lub na zewnątrz komponentu. -If a specific interaction still feels laggy, [use the React Developer Tools profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) to see which components benefit the most from memoization, and add memoization where needed. These principles make your components easier to debug and understand, so it's good to follow them in any case. In long term, we're researching [doing memoization automatically](https://www.youtube.com/watch?v=lGEMwh32soc) to solve this once and for all. +Jeśli jakieś działanie wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najbardziej korzystają z memoizacji, i dodaj memoizację tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatyczną memoizacją](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. - + -#### Skipping re-rendering with `useCallback` and `memo` {/*skipping-re-rendering-with-usecallback-and-memo*/} +#### Pomijanie przerenderowania za pomocą `useCallback` i `memo` {/*skipping-re-rendering-with-usecallback-and-memo*/} -In this example, the `ShippingForm` component is **artificially slowed down** so that you can see what happens when a React component you're rendering is genuinely slow. Try incrementing the counter and toggling the theme. +W tym przykładzie komponent `ShippingForm` jest **sztucznie spowolniony**, abyś mógł zobaczyć, co się dzieje, gdy komponent, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. -Incrementing the counter feels slow because it forces the slowed down `ShippingForm` to re-render. That's expected because the counter has changed, and so you need to reflect the user's new choice on the screen. +Zwiększanie licznika wydaje się wolne, ponieważ wymusza przerenderowanie spowolnionego komponentu `ShippingForm`. Jest to oczekiwane, ponieważ licznik się zmienił, więc musisz odzwierciedlić nowy wybór użytkownika na ekranie. -Next, try toggling the theme. **Thanks to `useCallback` together with [`memo`](/reference/react/memo), it’s fast despite the artificial slowdown!** `ShippingForm` skipped re-rendering because the `handleSubmit` function has not changed. The `handleSubmit` function has not changed because both `productId` and `referrer` (your `useCallback` dependencies) haven't changed since last render. +Następnie spróbuj przełączyć motyw. **Dzięki `useCallback` razem z [`memo`](/reference/react/memo), jest to szybkie pomimo sztucznego spowolnienia!** `ShippingForm` pominął przerenderowanie, ponieważ funkcja `handleSubmit` nie zmieniła się. Funkcja `handleSubmit` nie zmieniła się, ponieważ ani `productId`, ani `referrer` (twoje zależności w `useCallback`) nie zmieniły się od ostatniego przerenderowania. @@ -268,7 +268,7 @@ export default function App() { checked={isDark} onChange={e => setIsDark(e.target.checked)} /> - Dark mode + Ciemny motyw
'); + console.log('[SZTUCZNIE SPOWOLNIENIE] Renderowanie '); let startTime = performance.now(); while (performance.now() - startTime < 500) { - // Do nothing for 500 ms to emulate extremely slow code + // Nic nie rób przez 500 ms, aby symulować bardzo wolny kod } function handleSubmit(e) { @@ -331,23 +331,23 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { return (
-

Note: ShippingForm is artificially slowed down!

+

Uwaga: komponent ShippingForm jest sztucznie spowolniony!

@@ -386,11 +386,11 @@ button[type="button"] { -#### Always re-rendering a component {/*always-re-rendering-a-component*/} +#### Ciągłe przerenderowywanie komponentu {/*always-re-rendering-a-component*/} -In this example, the `ShippingForm` implementation is also **artificially slowed down** so that you can see what happens when some React component you're rendering is genuinely slow. Try incrementing the counter and toggling the theme. +W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyś mógł zobaczyć, co się dzieje, gdy jakiś komponent reaktowy, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. -Unlike in the previous example, toggling the theme is also slow now! This is because **there is no `useCallback` call in this version,** so `handleSubmit` is always a new function, and the slowed down `ShippingForm` component can't skip re-rendering. +W przeciwieństwie do poprzedniego przykładu, przełączanie motywu jest teraz również wolne! To dlatego, że **w tej wersji nie ma wywołania `useCallback`,** więc `handleSubmit` to zawsze nowa funkcja, przez co spowolniony komponent `ShippingForm` nie może pominąć przerenderowania. @@ -408,7 +408,7 @@ export default function App() { checked={isDark} onChange={e => setIsDark(e.target.checked)} /> - Dark mode + Ciemny motyw
'); let startTime = performance.now(); while (performance.now() - startTime < 500) { - // Do nothing for 500 ms to emulate extremely slow code + // Nic nie rób przez 500 ms, aby symulować bardzo wolny kod } function handleSubmit(e) { @@ -470,23 +470,23 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { return ( -

Note: ShippingForm is artificially slowed down!

+

Uwaga: komponent ShippingForm jest sztucznie spowolniony!

@@ -524,7 +524,7 @@ button[type="button"] {
-However, here is the same code **with the artificial slowdown removed.** Does the lack of `useCallback` feel noticeable or not? +Jednak tutaj jest ten sam kod **bez sztucznego spowolnienia.** Czy brak `useCallback` jest zauważalny czy nie? @@ -542,7 +542,7 @@ export default function App() { checked={isDark} onChange={e => setIsDark(e.target.checked)} /> - Dark mode + Ciemny motyw
'); + console.log('Renderowanie komponentu '); function handleSubmit(e) { e.preventDefault(); @@ -601,21 +601,21 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { return ( @@ -653,9 +653,9 @@ button[type="button"] {
-Quite often, code without memoization works fine. If your interactions are fast enough, you don't need memoization. +Dość często kod bez memoizacji działa dobrze. Jeśli twoje interakcje są wystarczająco szybkie, nie potrzebujesz memoizacji. -Keep in mind that you need to run React in production mode, disable [React Developer Tools](/learn/react-developer-tools), and use devices similar to the ones your app's users have in order to get a realistic sense of what's actually slowing down your app. +Pamiętaj, że musisz uruchomić React w trybie produkcyjnym, wyłączyć [Narzędzia Deweloperskie Reacta](/learn/react-developer-tools) oraz używać urządzeń podobnych do tych, które mają użytkownicy twojej aplikacji, aby uzyskać realistyczne odczucie, co tak naprawdę spowalnia twoją aplikację. From f41e6d758de2fc13d47d8eb0b04abc8fbd4b2bcd Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Sat, 19 Aug 2023 18:36:26 +0200 Subject: [PATCH 03/14] Part 3 - til end --- src/content/reference/react/useCallback.md | 78 +++++++++++----------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index fb55c2560..57d467979 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -663,11 +663,11 @@ Pamiętaj, że musisz uruchomić React w trybie produkcyjnym, wyłączyć [Narz --- -### Updating state from a memoized callback {/*updating-state-from-a-memoized-callback*/} +### Aktualizacja stanu z zapamiętanej funkcji zwrotnej (ang. *callback*) {/*updating-state-from-a-memoized-callback*/} -Sometimes, you might need to update state based on previous state from a memoized callback. +Czasami może być konieczne zaktualizowanie stanu na podstawie poprzedniego stanu z zapamiętanej funkcji zwrotnej. -This `handleAddTodo` function specifies `todos` as a dependency because it computes the next todos from it: +Funkcja `handleAddTodo` określa `todos` jako zależność, ponieważ oblicza następne zadania na jej podstawie: ```js {6,7} function TodoList() { @@ -680,7 +680,7 @@ function TodoList() { // ... ``` -You'll usually want memoized functions to have as few dependencies as possible. When you read some state only to calculate the next state, you can remove that dependency by passing an [updater function](/reference/react/useState#updating-state-based-on-the-previous-state) instead: +Zazwyczaj powinieneś dążyć do tego, aby zapamiętane funkcje miały jak najmniej zależności. Gdy odczytujesz pewien stan tylko po to, aby obliczyć następny stan, możesz usunąć tę zależność, przekazując zamiast tego [funkcję aktualizującą](/reference/react/useState#updating-state-based-on-the-previous-state): ```js {6,7} function TodoList() { @@ -689,17 +689,17 @@ function TodoList() { const handleAddTodo = useCallback((text) => { const newTodo = { id: nextId++, text }; setTodos(todos => [...todos, newTodo]); - }, []); // ✅ No need for the todos dependency + }, []); // ✅ Nie ma potrzeby, aby todos było zależnością // ... ``` -Here, instead of making `todos` a dependency and reading it inside, you pass an instruction about *how* to update the state (`todos => [...todos, newTodo]`) to React. [Read more about updater functions.](/reference/react/useState#updating-state-based-on-the-previous-state) +W tym przypadku zamiast robienia z `todos` zależność i odczytywania go wewnątrz funkcji, przekazujesz do Reacta instrukcję, jak *aktualizować* stan (`todos => [...todos, newTodo]`). [Dowiedz się więcej o funkcjach aktualizujących.](/reference/react/useState#updating-state-based-on-the-previous-state) --- -### Preventing an Effect from firing too often {/*preventing-an-effect-from-firing-too-often*/} +### Zapobieganie zbyt częstemu wyzwalaniu Efektu {/*preventing-an-effect-from-firing-too-often*/} -Sometimes, you might want to call a function from inside an [Effect:](/learn/synchronizing-with-effects) +Czasami może zdarzyć się, że chcesz wywołać funkcję wewnątrz [Efektu:](/learn/synchronizing-with-effects) ```js {4-9,12} function ChatRoom({ roomId }) { @@ -719,7 +719,7 @@ function ChatRoom({ roomId }) { // ... ``` -This creates a problem. [Every reactive value must be declared as a dependency of your Effect.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) However, if you declare `createOptions` as a dependency, it will cause your Effect to constantly reconnect to the chat room: +To tworzy problem. [Każda reaktywna wartość musi być zadeklarowana jako zależność twojego Efektu.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) Jednak jeśli zadeklarujesz `createOptions` jako zależność, spowoduje to, że twój Efekt będzie ciągle ponownie łączył się z pokojem czatowym: ```js {6} @@ -728,11 +728,11 @@ This creates a problem. [Every reactive value must be declared as a dependency o const connection = createConnection(); connection.connect(); return () => connection.disconnect(); - }, [createOptions]); // 🔴 Problem: This dependency changes on every render + }, [createOptions]); // 🔴 Problem: Ta zależność zmienia się z każdym renderowaniem // ... ``` -To solve this, you can wrap the function you need to call from an Effect into `useCallback`: +Aby to rozwiązać, możesz owrapować funkcję, którą musisz wywołać z Efektu, za pomocą `useCallback`: ```js {4-9,16} function ChatRoom({ roomId }) { @@ -743,25 +743,25 @@ function ChatRoom({ roomId }) { serverUrl: 'https://localhost:1234', roomId: roomId }; - }, [roomId]); // ✅ Only changes when roomId changes + }, [roomId]); // ✅ Zmienia się tylko wtedy, gdy zmienia się roomId useEffect(() => { const options = createOptions(); const connection = createConnection(); connection.connect(); return () => connection.disconnect(); - }, [createOptions]); // ✅ Only changes when createOptions changes + }, [createOptions]); // ✅ Zmienia się tylko wtedy, gdy zmienia się createOptions // ... ``` -This ensures that the `createOptions` function is the same between re-renders if the `roomId` is the same. **However, it's even better to remove the need for a function dependency.** Move your function *inside* the Effect: +To zapewnia, że funkcja `createOptions` pozostaje taka sama między przerenderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę zależności funkcji.** Przenieś swoją funkcję do *wewnętrza* Efektu: ```js {5-10,16} function ChatRoom({ roomId }) { const [message, setMessage] = useState(''); useEffect(() => { - function createOptions() { // ✅ No need for useCallback or function dependencies! + function createOptions() { // ✅ Nie ma potrzeby użycia useCallback ani zależności od funkcji! return { serverUrl: 'https://localhost:1234', roomId: roomId @@ -772,17 +772,17 @@ function ChatRoom({ roomId }) { const connection = createConnection(); connection.connect(); return () => connection.disconnect(); - }, [roomId]); // ✅ Only changes when roomId changes + }, [roomId]); // ✅ Zmienia się tylko wtedy, gdy zmienia się roomId // ... ``` -Now your code is simpler and doesn't need `useCallback`. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect) +Teraz twój kod jest prostszy i nie wymaga użycia `useCallback`. [Dowiedz się więcej o usuwaniu zależności Efektu.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect) --- -### Optimizing a custom Hook {/*optimizing-a-custom-hook*/} +### Optymalizacja własnego hooka {/*optimizing-a-custom-hook*/} -If you're writing a [custom Hook,](/learn/reusing-logic-with-custom-hooks) it's recommended to wrap any functions that it returns into `useCallback`: +Jeśli piszesz [własny hook,](/learn/reusing-logic-with-custom-hooks) zaleca się, aby owijać dowolne funkcje, które zwraca, za pomocą `useCallback`: ```js {4-6,8-10} function useRouter() { @@ -803,17 +803,17 @@ function useRouter() { } ``` -This ensures that the consumers of your Hook can optimize their own code when needed. +To zapewnia, że konsumenci (?) twojego hooka mogą zoptymalizować swój własny kod, gdy jest to potrzebne. --- -## Troubleshooting {/*troubleshooting*/} +## Znane problemy (?) {/*troubleshooting*/} -### Every time my component renders, `useCallback` returns a different function {/*every-time-my-component-renders-usecallback-returns-a-different-function*/} +### Za każdym razem, gdy mój komponent renderuje, `useCallback` zwraca inną funkcję {/*every-time-my-component-renders-usecallback-returns-a-different-function*/} -Make sure you've specified the dependency array as a second argument! +Upewnij się, że podałeś tablicę zależności jako drugi argument! -If you forget the dependency array, `useCallback` will return a new function every time: +Jeśli zapomnisz o tablicy zależności, `useCallback` będzie zwracać nową funkcję za każdym razem: ```js {7} function ProductPage({ productId, referrer }) { @@ -822,11 +822,11 @@ function ProductPage({ productId, referrer }) { referrer, orderDetails, }); - }); // 🔴 Returns a new function every time: no dependency array + }); // 🔴 Zwraca nową funkcję za każdym razem: brak tablicy zależności // ... ``` -This is the corrected version passing the dependency array as a second argument: +To jest poprawiona wersja, w której przekazujesz tablicę zależności jako drugi argument: ```js {7} function ProductPage({ productId, referrer }) { @@ -835,11 +835,11 @@ function ProductPage({ productId, referrer }) { referrer, orderDetails, }); - }, [productId, referrer]); // ✅ Does not return a new function unnecessarily + }, [productId, referrer]); // ✅ Nie zwraca niepotrzebnie nowej funkcji // ... ``` -If this doesn't help, then the problem is that at least one of your dependencies is different from the previous render. You can debug this problem by manually logging your dependencies to the console: +Jeśli to nie pomaga, problem może wynikać z tego, że przynajmniej jedna z twoich zależności różni się od poprzedniego renderowania. Możesz rozwiązać ten problem, dodając ręcznie logowanie twoich zależności do konsoli: ```js {5} const handleSubmit = useCallback((orderDetails) => { @@ -849,28 +849,28 @@ If this doesn't help, then the problem is that at least one of your dependencies console.log([productId, referrer]); ``` -You can then right-click on the arrays from different re-renders in the console and select "Store as a global variable" for both of them. Assuming the first one got saved as `temp1` and the second one got saved as `temp2`, you can then use the browser console to check whether each dependency in both arrays is the same: +Następnie kliknij prawym przyciskiem myszy na tablicach z różnych przerenderowań w konsoli i wybierz "Zachowaj jako zmienną globalną" (ang. *Save as global variable*) dla obu z nich. Zakładając, że pierwsza została zapisana jako `temp1`, a druga jako `temp2`, możesz następnie użyć konsoli przeglądarki, aby sprawdzić, czy każda zależność w obu tablicach jest taka sama: ```js -Object.is(temp1[0], temp2[0]); // Is the first dependency the same between the arrays? -Object.is(temp1[1], temp2[1]); // Is the second dependency the same between the arrays? -Object.is(temp1[2], temp2[2]); // ... and so on for every dependency ... +Object.is(temp1[0], temp2[0]); // Czy pierwsza zależność jest taka sama między tablicami? +Object.is(temp1[1], temp2[1]); // Czy druga zależność jest taka sama między tablicami? +Object.is(temp1[2], temp2[2]); // ... i tak dalej dla każdej zależności ... ``` -When you find which dependency is breaking memoization, either find a way to remove it, or [memoize it as well.](/reference/react/useMemo#memoizing-a-dependency-of-another-hook) +Kiedy znajdziesz, która zależność psuje zapamiętywanie, albo znajdź sposób, aby ją usunąć, albo [również ją zapamiętaj.](/reference/react/useMemo#memoizing-a-dependency-of-another-hook) --- -### I need to call `useCallback` for each list item in a loop, but it's not allowed {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} +### Muszę użyć `useCallback` dla każdego elementu listy w pętli, ale to nie jest dozwolone {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} -Suppose the `Chart` component is wrapped in [`memo`](/reference/react/memo). You want to skip re-rendering every `Chart` in the list when the `ReportList` component re-renders. However, you can't call `useCallback` in a loop: +Załóżmy, że komponent `Chart` jest owinęty w [`memo`](/reference/react/memo). Chcesz uniknąć przerenderowania każdego komponentu `Chart` na liście, gdy komponent `ReportList` zostanie ponownie przerysowany. Jednak nie możesz wywołać `useCallback` w pętli: ```js {5-14} function ReportList({ items }) { return (
{items.map(item => { - // 🔴 You can't call useCallback in a loop like this: + // 🔴 Nie możesz wywołać useCallback w pętli w ten sposób: const handleClick = useCallback(() => { sendReport(item) }, [item]); @@ -886,7 +886,7 @@ function ReportList({ items }) { } ``` -Instead, extract a component for an individual item, and put `useCallback` there: +Zamiast tego wyodrębnij komponent dla pojedynczego elementu i umieść w nim `useCallback`: ```js {5,12-21} function ReportList({ items }) { @@ -900,7 +900,7 @@ function ReportList({ items }) { } function Report({ item }) { - // ✅ Call useCallback at the top level: + // ✅ Wywołaj useCallback na najwyższym poziomie: const handleClick = useCallback(() => { sendReport(item) }, [item]); @@ -913,7 +913,7 @@ function Report({ item }) { } ``` -Alternatively, you could remove `useCallback` in the last snippet and instead wrap `Report` itself in [`memo`.](/reference/react/memo) If the `item` prop does not change, `Report` will skip re-rendering, so `Chart` will skip re-rendering too: +Ewentualnie, możesz usunąć `useCallback` z ostatniego fragmentu kodu i zamiast tego owinąć sam komponent `Report` w [`memo`.](/reference/react/memo) Jeśli wlaściwość `item` się nie zmienia, komponent `Report` pominie przerenderowanie, a zatem komponent `Chart` również pominie przerenderowanie: ```js {5,6-8,15} function ReportList({ items }) { From ceb6693a7512a2c3c4d434b404957204f2ad567e Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Sat, 19 Aug 2023 22:27:25 +0200 Subject: [PATCH 04/14] Minor fixes --- src/content/reference/react/useCallback.md | 75 +++++++++++----------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 57d467979..214ed04d1 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -40,18 +40,18 @@ export default function ProductPage({ productId, referrer, theme }) { * `fn`: Funkcja, którą chcesz zapamiętać. Może przyjąć dowolne argumenty i zwrócić dowolne wartości. React zwróci (nie wywoła!) twoją funkcję z powrotem w pierwszym renderowaniu. Przy kolejnych renderowaniach, React zwróci ci tę samą funkcję ponownie jeśli lista zależności `dependencies` nie zmieni się od ostatniego renderowania. W przeciwnym razie zwróci ci funkcję, którą przekazałeś podczas obecnego renderowania i zachowa ją do ponownego użycia potem. React nie wywoła twojej funkcji. Funkcja ta zostanie ci zwrócona, abyś mógł sam wybrać gdzie i kiedy ma być wywołana. -* `dependencies`: Lista wszystkich reaktywnych (?) wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała (?) komponentu. Jeżeli twój linter jest [skonfigurowany dla Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost (?) jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). +* `dependencies`: Lista wszystkich reaktywnych wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała komponentu. Jeżeli twój linter jest [skonfigurowany dla Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). -#### Zwracan wartość {/*returns*/} +#### Zwracana wartość {/*returns*/} -Podczas pierwszego renderowania, `useCallback` zwróci funkcję `fn` którą przekazałeś. +Podczas pierwszego renderowania, `useCallback` zwróci funkcję `fn`, którą mu przekazałeś. Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z poprzedniego renderowania (jeśli zależności nie uległy zmianie) albo zwróci funkcję `fn`, którą przekazałeś podczas tego renderowania. #### Zastrzeżenia {/*caveats*/} * `useCallback` jest hookiem, więc można go wywoływać tylko **na głównym poziomie komponentu** lub innego hooka. Nie można go wywołać w pętli lub instrukcji warunkowej. Jeśli masz sytuację, która wymaga pętli lub warunku, stwórz nowy komponent i przenieś do niego ten stan. -* React **nie odrzuci zapamiętanej funkcji chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania (?). W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar (?) zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. +* React **nie odrzuci zapamiętanej funkcji chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję, gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania. W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens, aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. --- @@ -59,7 +59,7 @@ Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z pop ### Pomijanie przerenderowywania komponentów {/*skipping-re-rendering-of-components*/} -Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do potomków komponentów. Spójrzmy najpierw na składnię jak to zrobić, a potem w jakich przypadkach jest to przydatne. +Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do elementów potomnych. Spójrzmy najpierw na składnię jak to zrobić, a potem w jakich przypadkach jest to przydatne. Aby zapamiętać funkcję pomiędzy renderowaniami twojego komponentu, zawrzyj jej definicję w hooku `useCallback`: @@ -87,7 +87,7 @@ Przy następnych renderowaniach, React porówna zależności< Innymi słowy, `useCallback` zapamięta funkcję pomiędzy przerenderowaniami dopóki zależności się nie zmienią. -**Posłużmy się przykładem aby zobaczyć kiedy to może być przydatne.** +**Posłużmy się przykładem, aby zobaczyć kiedy to może być przydatne.** Załóżmy, że przekazujesz funkcję `handleSubmit` w dół z `ProductPage` do komponentu `ShippingForm`: @@ -101,13 +101,9 @@ function ProductPage({ productId, referrer, theme }) { ); ``` -You've noticed that toggling the `theme` prop freezes the app for a moment, but if you remove `` from your JSX, it feels fast. This tells you that it's worth trying to optimize the `ShippingForm` component. -Zauważyłeś, że zmienianie właściwości `theme` zatrzymuje na chwilę aplikację, ale gdy usuniesz `` from twojego JSX, zauważysz, że znów działa szybko. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. +Zauważyłeś, że przełączanie właściwości `theme` blokuje na chwilę aplikację, ale gdy usuniesz `` z twojego JSX, zauważysz, że znów działa gładko. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. -**By default, when a component re-renders, React re-renders all of its children recursively.** This is why, when `ProductPage` re-renders with a different `theme`, the `ShippingForm` component *also* re-renders. This is fine for components that don't require much calculation to re-render. But if you verified a re-render is slow, you can tell `ShippingForm` to skip re-rendering when its props are the same as on last render by wrapping it in [`memo`:](/reference/react/memo) -**Domyślnie, kiedy komponent się przerenderowuje, React przerenderowuje rekurencyjnie wszystkie jego elementy potomne.** To dlatego gdy `ProductPage` przerenderowu - -**Domyślnie, gdy komponent zostaje ponownie przerenderowany, React przerenderowuje rekursywnie wszystkie jego elementy potomne.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. To jest w porządku dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli sprawdziłeś, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowywania, owijając (?) go w [`memo`:](/reference/react/memo) +**Domyślnie, gdy komponent jest ponownie przerenderowywany, React także przerenderowuje rekursywnie wszystkie jego elementy potomne.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli upewniłeś się, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowania, owijając (?) go w [`memo`:](/reference/react/memo) ```js {3,5} import { memo } from 'react'; @@ -117,10 +113,11 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { }); ``` -**Po dokonaniu tej zmiany, komponent `ShippingForm` pominie przerenderowanie, jeśli wszystkie jego właściwości są *takie same* jak podczas ostatniego renderowania.** To jest moment, w którym istotne staje się zapamitywanie (?) funkcji! Załóżmy, że zdefiniowałeś funkcję `handleSubmit` bez użycia hooka `useCallback`: +**Po dokonaniu tej zmiany, komponent `ShippingForm` pominie przerenderowanie, jeśli wszystkie jego właściwości są *takie same* jak podczas ostatniego renderowania.** To jest moment, w którym istotne staje się zapamiętywanie funkcji! Załóżmy, że zdefiniowałeś funkcję `handleSubmit` bez użycia hooka `useCallback`: ```js {2,3,8,12-13} function ProductPage({ productId, referrer, theme }) { + // Za każdym razem, gdy zmienia się theme, to będzie inna funkcja... function handleSubmit(orderDetails) { post('/product/' + productId + '/buy', { referrer, @@ -137,11 +134,11 @@ function ProductPage({ productId, referrer, theme }) { } ``` -**W języku JavaScript, `function () {}` lub `() => {}` zawsze tworzy _inną_ funkcję,** podobnie jak literał obiektu `{}` zawsze tworzy nowy obiekt. Zazwyczaj nie byłoby to problemem, ale oznacza to, że właściwości komponentu `ShippingForm` nigdy nie będą takie same, i optymalizacja [`memo`](/reference/react/memo) nie zadziała. Tutaj przydaje się `useCallback`: +**W języku JavaScript, `function () {}` lub `() => {}` zawsze tworzy _inną_ funkcję,** podobnie jak literał obiektu `{}` zawsze tworzy nowy obiekt. Zazwyczaj nie byłoby to problemem, ale oznacza to, że właściwości komponentu `ShippingForm` nigdy nie będą takie same i optymalizacja [`memo`](/reference/react/memo) nie zadziała. Tutaj `useCallback` staje się pomocny: ```js {2,3,8,12-13} function ProductPage({ productId, referrer, theme }) { - // Powiedz Reactowi, aby zapamiętał Twoją funkcję między przerenderowaniami... + // Powiedz Reactowi, aby zapamiętał twoją funkcję między przerenderowaniami... const handleSubmit = useCallback((orderDetails) => { post('/product/' + productId + '/buy', { referrer, @@ -170,7 +167,7 @@ function ProductPage({ productId, referrer, theme }) { #### Jaki jest związek między useCallback a useMemo? {/*how-is-usecallback-related-to-usememo*/} -Często zobaczysz [`useMemo`](/reference/react/useMemo) obok `useCallback`. Oba są przydatne, gdy próbujesz zoptymalizować komponent potomny. Pozwalają one na [memoizację](https://pl.wikipedia.org/wiki/Memoization) (lub inaczej mówiąc, buforowanie (?)) tego, co przekazujesz w dół: +Często zobaczysz [`useMemo`](/reference/react/useMemo) obok `useCallback`. Oba są przydatne, gdy próbujesz zoptymalizować komponent potomny. Pozwalają one na [memoizację](https://en.wikipedia.org/wiki/Memoization) (lub inaczej mówiąc, zapamiętywanie) tego, co przekazujesz w dół: ```js {6-8,10-15,19} import { useMemo, useCallback } from 'react'; @@ -197,10 +194,10 @@ function ProductPage({ productId, referrer }) { } ``` -Różnica polega na tym *co* pozwalają ci buforować (?): +Różnica polega na tym *co* pozwalają ci zapamiętać: -* **[`useMemo`](/reference/react/useMemo) buforuje (?) *wynik* wywołania Twojej funkcji.** W tym przykładzie buforuje wynik wywołania `computeRequirements(product)`, aby nie zmieniał się, chyba że zmieni się `product`. Pozwala to przekazywać obiekt `requirements` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Gdy będzie to konieczne, React wywoła funkcję, którą przekazałeś podczas renderowania, aby obliczyć wynik. -* **`useCallback` buforuje *samą funkcję*.** W przeciwieństwie do `useMemo`, nie wywołuje dostarczonej funkcji. Zamiast tego buforuje funkcję, którą podałeś, tak aby `handleSubmit` *sam* nie zmieniał się, chyba że zmieni się `productId` lub `referrer`. Pozwala to przekazywać funkcję `handleSubmit` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Twój kod nie zostanie uruchomiony, dopóki użytkownik nie prześle formularza. +* **[`useMemo`](/reference/react/useMemo) zapamiętuje *wynik* wywołania twojej funkcji.** W tym przykładzie jest to wynik wywołania `computeRequirements(product)`, aby nie zmieniał się, chyba że zmieni się `product`. Pozwala to przekazywać obiekt `requirements` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Gdy będzie to konieczne, React wywoła funkcję, którą przekazałeś podczas renderowania, aby obliczyć wynik. +* **`useCallback` zapamiętuje *samą funkcję*.** W przeciwieństwie do `useMemo`, nie wywołuje dostarczonej funkcji. Zamiast tego zapamiętuje funkcję, którą podałeś, tak aby `handleSubmit` *sam* nie zmieniał się, chyba że zmieni się `productId` lub `referrer`. Pozwala to przekazywać funkcję `handleSubmit` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Twój kod nie zostanie uruchomiony, dopóki użytkownik nie prześle formularza. Jeśli już jesteś zaznajomiony z [`useMemo`,](/reference/react/useMemo) pomocne może być myślenie o `useCallback` w ten sposób: @@ -219,26 +216,26 @@ function useCallback(fn, dependencies) { #### Czy powinieneś używać useCallback wszędzie? {/*should-you-add-usecallback-everywhere*/} -Jeśli twoja aplikacja jest podobna do tej strony i większość interakcji jest prostych (takich jak zastępowanie strony lub całej sekcji), to zazwyczaj memoizacja nie jest konieczna. Z drugiej strony, jeśli twoja aplikacja przypomina edytor rysunków i większość interakcji jest dość szczegółowa (takie jak przesuwanie kształtów), to możliwe, że memoizacja będzie bardzo pomocna. +Jeśli twoja aplikacja jest podobna do tej strony i większość interakcji jest prostych (takich jak zastępowanie strony lub całej sekcji), to zazwyczaj zapamiętywanie nie jest konieczne. Z drugiej strony, jeśli twoja aplikacja przypomina edytor rysunków i większość interakcji jest dość szczegółowa (takie jak przesuwanie kształtów), to możliwe, że zapamiętywanie będzie bardzo pomocne. -Buforowanie funkcji za pomocą `useCallback` ma wartość tylko w kilku przypadkach: +Zapamiętywanie funkcji za pomocą `useCallback` daje wyraźne korzyści tylko w kilku przypadkach: -- Przekazujesz ją jako element potomny do komponentu owiniętego w [`memo`.](/reference/react/memo) Chcesz pominąć przerysowywanie, jeśli wartość się nie zmieniła. Memoizacja pozwala komponentowi przerysować się tylko wtedy, gdy zmienią się zależności. +- Przekazujesz ją jako element potomny do komponentu owiniętego w [`memo`.](/reference/react/memo) Chcesz pominąć przerenderowanie, jeśli wartość się nie zmieniła. Zapamiętywanie pozwala komponentowi przerenderować się tylko wtedy, gdy zmienią się zależności. - Funkcja, którą przekazujesz, jest później używana jako zależność pewnego Hooka. Na przykład inna funkcja owinięta w `useCallback` zależy od niej, lub ty zależysz od tej funkcji w [`useEffect.`](/reference/react/useEffect) -W innych przypadkach nie ma korzyści z owijania funkcji w `useCallback`. Nie ma to również znaczącego wpływu na działanie, więc niektóre zespoły wybierają, by nie zastanawiać się nad indywidualnymi przypadkami i stosować buforowanie tak często, jak to możliwe. Wadą tego podejścia jest jednak to, że kod staje się mniej czytelny. Dodatkowo, nie zawsze memoizacja jest skuteczna: pojedyncza wartość, która "zawsze jest nowa", może wystarczyć, aby zepsuć memoizację dla całego komponentu. +W innych przypadkach nie ma korzyści z owijania funkcji w `useCallback`. Nie ma to również znaczącego wpływu na działanie, więc niektóre zespoły wybierają, by nie zastanawiać się nad indywidualnymi przypadkami i stosować zapamiętywanie tak często, jak to możliwe. Wadą tego podejścia jest jednak to, że kod staje się mniej czytelny. Dodatkowo, nie zawsze zapamiętywanie jest skuteczne: pojedyncza wartość, która "zawsze jest nowa", może wystarczyć, aby zepsuć zapamiętywanie dla całego komponentu. -Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze tworzysz funkcję (i to jest w porządku!), ale React ją ignoruje i zwraca buforowaną funkcję, jeśli nic się nie zmieniło. +Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze tworzysz funkcję (i to jest w porządku!), ale React ją ignoruje i zwraca zapamiętaną funkcję, jeśli nic się nie zmieniło. -**W praktyce możesz uniknąć wielu przypadków memoizacji, stosując kilka zasad:** +**W praktyce możesz uniknąć wielu przypadków zapamiętywania, stosując kilka zasad:** 1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent warpujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. 1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj nietrwałego (?) stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w globalnej bibliotece stanu. -1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw błąd zamiast dodawać memoizację. -1. Unikaj [niepotrzebnych Efektów (?), które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w Efektach i prowadzą do wielokrotnego przerenderowania komponentów. -1. Staraj się [usunąć niepotrzebne zależności z Efektów.](/learn/removing-effect-dependencies) Na przykład zamiast memoizacji, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do Efektu lub na zewnątrz komponentu. +1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw błąd zamiast dodawać zapamiętywanie. +1. Unikaj [niepotrzebnych Efektów, które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w Efektach i prowadzą do wielokrotnego przerenderowania komponentów. +1. Staraj się [usunąć niepotrzebne zależności z Efektów.](/learn/removing-effect-dependencies) Na przykład zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do Efektu lub na zewnątrz komponentu. -Jeśli jakieś działanie wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najbardziej korzystają z memoizacji, i dodaj memoizację tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatyczną memoizacją](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. +Jeśli jakaś interakcja wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najbardziej korzystają z zapamiętywania, i dodaj zapamiętywanie tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatycznym zapamiętywaniem](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. @@ -313,7 +310,7 @@ import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { const [count, setCount] = useState(1); - console.log('[SZTUCZNIE SPOWOLNIENIE] Renderowanie '); + console.log('[SZTUCZNE SPOWOLNIENIE] Renderowanie '); let startTime = performance.now(); while (performance.now() - startTime < 500) { // Nic nie rób przez 500 ms, aby symulować bardzo wolny kod @@ -388,7 +385,7 @@ button[type="button"] { #### Ciągłe przerenderowywanie komponentu {/*always-re-rendering-a-component*/} -W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyś mógł zobaczyć, co się dzieje, gdy jakiś komponent reaktowy, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. +W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyś mógł zobaczyć, co się dzieje, gdy jakiś komponent reactowy, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. W przeciwieństwie do poprzedniego przykładu, przełączanie motywu jest teraz również wolne! To dlatego, że **w tej wersji nie ma wywołania `useCallback`,** więc `handleSubmit` to zawsze nowa funkcja, przez co spowolniony komponent `ShippingForm` nie może pominąć przerenderowania. @@ -452,7 +449,7 @@ import { memo, useState } from 'react'; const ShippingForm = memo(function ShippingForm({ onSubmit }) { const [count, setCount] = useState(1); - console.log('[ARTIFICIALLY SLOW] Rendering '); + console.log('[SZTUCZNE SPOWOLNIENIE] Renderowanie '); let startTime = performance.now(); while (performance.now() - startTime < 500) { // Nic nie rób przez 500 ms, aby symulować bardzo wolny kod @@ -653,7 +650,7 @@ button[type="button"] { -Dość często kod bez memoizacji działa dobrze. Jeśli twoje interakcje są wystarczająco szybkie, nie potrzebujesz memoizacji. +Dość często kod bez zapamiętywania działa dobrze. Jeśli twoje interakcje są wystarczająco szybkie, nie potrzebujesz zapamiętywania. Pamiętaj, że musisz uruchomić React w trybie produkcyjnym, wyłączyć [Narzędzia Deweloperskie Reacta](/learn/react-developer-tools) oraz używać urządzeń podobnych do tych, które mają użytkownicy twojej aplikacji, aby uzyskać realistyczne odczucie, co tak naprawdę spowalnia twoją aplikację. @@ -807,9 +804,9 @@ To zapewnia, że konsumenci (?) twojego hooka mogą zoptymalizować swój własn --- -## Znane problemy (?) {/*troubleshooting*/} +## Znane problemy {/*troubleshooting*/} -### Za każdym razem, gdy mój komponent renderuje, `useCallback` zwraca inną funkcję {/*every-time-my-component-renders-usecallback-returns-a-different-function*/} +### Za każdym razem, gdy mój komponent renderuje się, `useCallback` zwraca inną funkcję {/*every-time-my-component-renders-usecallback-returns-a-different-function*/} Upewnij się, że podałeś tablicę zależności jako drugi argument! @@ -839,7 +836,7 @@ function ProductPage({ productId, referrer }) { // ... ``` -Jeśli to nie pomaga, problem może wynikać z tego, że przynajmniej jedna z twoich zależności różni się od poprzedniego renderowania. Możesz rozwiązać ten problem, dodając ręcznie logowanie twoich zależności do konsoli: +Jeśli to nie pomaga, problem może wynikać z tego, że przynajmniej jedna z twoich zależności zmieniła się od poprzedniego renderowania. Możesz rozwiązać ten problem, dodając ręcznie logowanie twoich zależności do konsoli: ```js {5} const handleSubmit = useCallback((orderDetails) => { @@ -849,7 +846,7 @@ Jeśli to nie pomaga, problem może wynikać z tego, że przynajmniej jedna z tw console.log([productId, referrer]); ``` -Następnie kliknij prawym przyciskiem myszy na tablicach z różnych przerenderowań w konsoli i wybierz "Zachowaj jako zmienną globalną" (ang. *Save as global variable*) dla obu z nich. Zakładając, że pierwsza została zapisana jako `temp1`, a druga jako `temp2`, możesz następnie użyć konsoli przeglądarki, aby sprawdzić, czy każda zależność w obu tablicach jest taka sama: +Następnie w konsoli kliknij prawym przyciskiem myszy na tablicach z różnych przerenderowań i wybierz "Zachowaj jako zmienną globalną" (ang. *Save as global variable*) dla obu z nich. Zakładając, że pierwsza została zapisana jako `temp1`, a druga jako `temp2`, możesz następnie użyć konsoli przeglądarki, aby sprawdzić, czy każda zależność w obu tablicach jest taka sama: ```js Object.is(temp1[0], temp2[0]); // Czy pierwsza zależność jest taka sama między tablicami? @@ -861,9 +858,9 @@ Kiedy znajdziesz, która zależność psuje zapamiętywanie, albo znajdź sposó --- -### Muszę użyć `useCallback` dla każdego elementu listy w pętli, ale to nie jest dozwolone {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} +### Muszę użyć `useCallback` dla każdego elementu listy w pętli, ale nie jest to dozwolone {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} -Załóżmy, że komponent `Chart` jest owinęty w [`memo`](/reference/react/memo). Chcesz uniknąć przerenderowania każdego komponentu `Chart` na liście, gdy komponent `ReportList` zostanie ponownie przerysowany. Jednak nie możesz wywołać `useCallback` w pętli: +Załóżmy, że komponent `Chart` jest owinęty w [`memo`](/reference/react/memo). Chcesz uniknąć przerenderowania każdego komponentu `Chart` na liście, gdy komponent `ReportList` zostanie ponownie przerenderowany. Jednak nie możesz wywołać `useCallback` w pętli: ```js {5-14} function ReportList({ items }) { From d1a7b6d3c1a116a71d2bee76fdec71882a2c01aa Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Sun, 20 Aug 2023 00:14:34 +0200 Subject: [PATCH 05/14] Minor fixes --- src/content/reference/react/useCallback.md | 46 +++++++++++----------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 214ed04d1..b5ad31bec 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -4,7 +4,7 @@ title: useCallback -`useCallback` jest hookiem reactowym, który pozwala na zapamiętywanie (ang. cache) definicji funkcji pomiędzy przerenderowaniami. +`useCallback` jest hookiem reactowym, który pozwala na zapamiętywanie (ang. cache, memoize) definicji funkcji pomiędzy przerenderowaniami. ```js const cachedFn = useCallback(fn, dependencies) @@ -40,18 +40,18 @@ export default function ProductPage({ productId, referrer, theme }) { * `fn`: Funkcja, którą chcesz zapamiętać. Może przyjąć dowolne argumenty i zwrócić dowolne wartości. React zwróci (nie wywoła!) twoją funkcję z powrotem w pierwszym renderowaniu. Przy kolejnych renderowaniach, React zwróci ci tę samą funkcję ponownie jeśli lista zależności `dependencies` nie zmieni się od ostatniego renderowania. W przeciwnym razie zwróci ci funkcję, którą przekazałeś podczas obecnego renderowania i zachowa ją do ponownego użycia potem. React nie wywoła twojej funkcji. Funkcja ta zostanie ci zwrócona, abyś mógł sam wybrać gdzie i kiedy ma być wywołana. -* `dependencies`: Lista wszystkich reaktywnych wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała komponentu. Jeżeli twój linter jest [skonfigurowany dla Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). +* `dependencies`: Lista wszystkich reaktywnych wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała komponentu. Jeżeli twój linter jest [skonfigurowany pod Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). #### Zwracana wartość {/*returns*/} -Podczas pierwszego renderowania, `useCallback` zwróci funkcję `fn`, którą mu przekazałeś. +Podczas pierwszego renderowania, `useCallback` zwróci funkcję `fn`, która została mu przekazana. Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z poprzedniego renderowania (jeśli zależności nie uległy zmianie) albo zwróci funkcję `fn`, którą przekazałeś podczas tego renderowania. #### Zastrzeżenia {/*caveats*/} * `useCallback` jest hookiem, więc można go wywoływać tylko **na głównym poziomie komponentu** lub innego hooka. Nie można go wywołać w pętli lub instrukcji warunkowej. Jeśli masz sytuację, która wymaga pętli lub warunku, stwórz nowy komponent i przenieś do niego ten stan. -* React **nie odrzuci zapamiętanej funkcji chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję, gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania. W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens, aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. +* React **nie odrzuci zapamiętanej funkcji, chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję, gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania. W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens, aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. --- @@ -59,7 +59,7 @@ Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z pop ### Pomijanie przerenderowywania komponentów {/*skipping-re-rendering-of-components*/} -Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do elementów potomnych. Spójrzmy najpierw na składnię jak to zrobić, a potem w jakich przypadkach jest to przydatne. +Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do potomków. Spójrzmy najpierw na składnię jak to zrobić, a potem w jakich przypadkach jest to przydatne. Aby zapamiętać funkcję pomiędzy renderowaniami twojego komponentu, zawrzyj jej definicję w hooku `useCallback`: @@ -103,7 +103,7 @@ function ProductPage({ productId, referrer, theme }) { Zauważyłeś, że przełączanie właściwości `theme` blokuje na chwilę aplikację, ale gdy usuniesz `` z twojego JSX, zauważysz, że znów działa gładko. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. -**Domyślnie, gdy komponent jest ponownie przerenderowywany, React także przerenderowuje rekursywnie wszystkie jego elementy potomne.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli upewniłeś się, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowania, owijając (?) go w [`memo`:](/reference/react/memo) +**Domyślnie, gdy komponent jest ponownie przerenderowywany, React także przerenderowuje rekursywnie wszystkich jego potomków.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli upewniłeś się, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowania, owijając (?) go w [`memo`:](/reference/react/memo) ```js {3,5} import { memo } from 'react'; @@ -148,7 +148,7 @@ function ProductPage({ productId, referrer, theme }) { return (
- {/* ...ShippingForm otrzyma te same elementy potomne i może pominąć przerenderowanie */} + {/* ...ShippingForm otrzyma tych samych potomków i może pominąć przerenderowanie */}
); @@ -220,22 +220,22 @@ Jeśli twoja aplikacja jest podobna do tej strony i większość interakcji jest Zapamiętywanie funkcji za pomocą `useCallback` daje wyraźne korzyści tylko w kilku przypadkach: -- Przekazujesz ją jako element potomny do komponentu owiniętego w [`memo`.](/reference/react/memo) Chcesz pominąć przerenderowanie, jeśli wartość się nie zmieniła. Zapamiętywanie pozwala komponentowi przerenderować się tylko wtedy, gdy zmienią się zależności. -- Funkcja, którą przekazujesz, jest później używana jako zależność pewnego Hooka. Na przykład inna funkcja owinięta w `useCallback` zależy od niej, lub ty zależysz od tej funkcji w [`useEffect.`](/reference/react/useEffect) +- Przekazujesz ją jako właściwość do potomka, który jest owinięty w [`memo`.](/reference/react/memo) Chcesz pominąć przerenderowanie, jeśli wartość się nie zmieniła. Zapamiętywanie pozwala komponentowi przerenderować się tylko wtedy, gdy zmienią się zależności. +- Funkcja, którą przekazujesz, jest później używana jako zależność jakiegoś Hooka. Na przykład inna funkcja owinięta w `useCallback` zależy od niej lub ty zależysz od tej funkcji w hooku [`useEffect.`](/reference/react/useEffect) W innych przypadkach nie ma korzyści z owijania funkcji w `useCallback`. Nie ma to również znaczącego wpływu na działanie, więc niektóre zespoły wybierają, by nie zastanawiać się nad indywidualnymi przypadkami i stosować zapamiętywanie tak często, jak to możliwe. Wadą tego podejścia jest jednak to, że kod staje się mniej czytelny. Dodatkowo, nie zawsze zapamiętywanie jest skuteczne: pojedyncza wartość, która "zawsze jest nowa", może wystarczyć, aby zepsuć zapamiętywanie dla całego komponentu. -Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze tworzysz funkcję (i to jest w porządku!), ale React ją ignoruje i zwraca zapamiętaną funkcję, jeśli nic się nie zmieniło. +Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze tworzysz funkcję (i nie ma w tym nic złego!), ale React ją ignoruje i zwraca zapamiętaną funkcję, jeśli nic się nie zmieniło. **W praktyce możesz uniknąć wielu przypadków zapamiętywania, stosując kilka zasad:** -1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent warpujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. -1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj nietrwałego (?) stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w globalnej bibliotece stanu. -1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw błąd zamiast dodawać zapamiętywanie. +1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent wrapujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. +1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj nietrwałego (?) stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w bibliotece globalnego stanu. +1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw go zamiast dodawać zapamiętywanie. 1. Unikaj [niepotrzebnych Efektów, które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w Efektach i prowadzą do wielokrotnego przerenderowania komponentów. 1. Staraj się [usunąć niepotrzebne zależności z Efektów.](/learn/removing-effect-dependencies) Na przykład zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do Efektu lub na zewnątrz komponentu. -Jeśli jakaś interakcja wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najbardziej korzystają z zapamiętywania, i dodaj zapamiętywanie tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatycznym zapamiętywaniem](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. +Jeśli jakaś interakcja wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najwięcej zyskują na zapamiętywaniu i dodaj zapamiętywanie tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatycznym zapamiętywaniem](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. @@ -347,7 +347,7 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { Kod pocztowy: - + ); }); @@ -385,9 +385,9 @@ button[type="button"] { #### Ciągłe przerenderowywanie komponentu {/*always-re-rendering-a-component*/} -W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyś mógł zobaczyć, co się dzieje, gdy jakiś komponent reactowy, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. +W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyś mógł zobaczyć, co się dzieje, gdy komponent reactowy, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. -W przeciwieństwie do poprzedniego przykładu, przełączanie motywu jest teraz również wolne! To dlatego, że **w tej wersji nie ma wywołania `useCallback`,** więc `handleSubmit` to zawsze nowa funkcja, przez co spowolniony komponent `ShippingForm` nie może pominąć przerenderowania. +W przeciwieństwie do poprzedniego przykładu, przełączanie motywu jest teraz również wolne! To dlatego, że **w tej wersji nie ma wywołania `useCallback`,** więc `handleSubmit` jest zawsze nową funkcją, przez co spowolniony komponent `ShippingForm` nie może pominąć przerenderowania. @@ -486,7 +486,7 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { Kod pocztowy: - + ); }); @@ -521,7 +521,7 @@ button[type="button"] { -Jednak tutaj jest ten sam kod **bez sztucznego spowolnienia.** Czy brak `useCallback` jest zauważalny czy nie? +Natomiast tutaj jest ten sam kod **bez sztucznego spowolnienia.** Czy brak `useCallback` jest tu zauważalny? @@ -615,7 +615,7 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { Kod pocztowy: - + ); }); @@ -664,7 +664,7 @@ Pamiętaj, że musisz uruchomić React w trybie produkcyjnym, wyłączyć [Narz Czasami może być konieczne zaktualizowanie stanu na podstawie poprzedniego stanu z zapamiętanej funkcji zwrotnej. -Funkcja `handleAddTodo` określa `todos` jako zależność, ponieważ oblicza następne zadania na jej podstawie: +Funkcja `handleAddTodo` posiada `todos` jako zależność, ponieważ oblicza następne zadania na jej podstawie: ```js {6,7} function TodoList() { @@ -677,7 +677,7 @@ function TodoList() { // ... ``` -Zazwyczaj powinieneś dążyć do tego, aby zapamiętane funkcje miały jak najmniej zależności. Gdy odczytujesz pewien stan tylko po to, aby obliczyć następny stan, możesz usunąć tę zależność, przekazując zamiast tego [funkcję aktualizującą](/reference/react/useState#updating-state-based-on-the-previous-state): +Zazwyczaj powinieneś dążyć do tego, aby zapamiętane funkcje miały jak najmniej zależności. Gdy odczytujesz pewien stan tylko po to, aby obliczyć jego następną wartość, możesz usunąć tę zależność, przekazując zamiast tego [funkcję aktualizującą](/reference/react/useState#updating-state-based-on-the-previous-state): ```js {6,7} function TodoList() { @@ -716,7 +716,7 @@ function ChatRoom({ roomId }) { // ... ``` -To tworzy problem. [Każda reaktywna wartość musi być zadeklarowana jako zależność twojego Efektu.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) Jednak jeśli zadeklarujesz `createOptions` jako zależność, spowoduje to, że twój Efekt będzie ciągle ponownie łączył się z pokojem czatowym: +To powoduje pewien problem. [Każda reaktywna wartość musi być zadeklarowana jako zależność twojego Efektu.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) Jednak jeśli zadeklarujesz `createOptions` jako zależność, spowoduje to, że twój Efekt będzie ciągle ponawiał łączenie się z pokojem czatowym: ```js {6} From 4ab412987e9ed2237d8c6a843af2bc70c8b15e78 Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Sun, 20 Aug 2023 00:19:57 +0200 Subject: [PATCH 06/14] Typo fixes --- src/content/reference/react/useCallback.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index b5ad31bec..b9c0c27d2 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -751,7 +751,7 @@ function ChatRoom({ roomId }) { // ... ``` -To zapewnia, że funkcja `createOptions` pozostaje taka sama między przerenderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę zależności funkcji.** Przenieś swoją funkcję do *wewnętrza* Efektu: +To zapewnia, że funkcja `createOptions` pozostaje taka sama między przerenderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę zależności funkcji.** Przenieś swoją funkcję do *wnętrza* Efektu: ```js {5-10,16} function ChatRoom({ roomId }) { @@ -860,7 +860,7 @@ Kiedy znajdziesz, która zależność psuje zapamiętywanie, albo znajdź sposó ### Muszę użyć `useCallback` dla każdego elementu listy w pętli, ale nie jest to dozwolone {/*i-need-to-call-usememo-for-each-list-item-in-a-loop-but-its-not-allowed*/} -Załóżmy, że komponent `Chart` jest owinęty w [`memo`](/reference/react/memo). Chcesz uniknąć przerenderowania każdego komponentu `Chart` na liście, gdy komponent `ReportList` zostanie ponownie przerenderowany. Jednak nie możesz wywołać `useCallback` w pętli: +Załóżmy, że komponent `Chart` jest owinięty w [`memo`](/reference/react/memo). Chcesz uniknąć przerenderowania każdego komponentu `Chart` na liście, gdy komponent `ReportList` zostanie ponownie przerenderowany. Jednak nie możesz wywołać `useCallback` w pętli: ```js {5-14} function ReportList({ items }) { @@ -910,7 +910,7 @@ function Report({ item }) { } ``` -Ewentualnie, możesz usunąć `useCallback` z ostatniego fragmentu kodu i zamiast tego owinąć sam komponent `Report` w [`memo`.](/reference/react/memo) Jeśli wlaściwość `item` się nie zmienia, komponent `Report` pominie przerenderowanie, a zatem komponent `Chart` również pominie przerenderowanie: +Ewentualnie, możesz usunąć `useCallback` z ostatniego fragmentu kodu i zamiast tego owinąć sam komponent `Report` w [`memo`.](/reference/react/memo) Jeśli właściwość `item` się nie zmienia, komponent `Report` pominie przerenderowanie, a zatem komponent `Chart` również pominie przerenderowanie: ```js {5,6-8,15} function ReportList({ items }) { From 9fffebfcef9bc790d459e5b45d2368fe7fc61f8d Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Tue, 22 Aug 2023 21:44:21 +0200 Subject: [PATCH 07/14] Fix translation for wrap word, fix case issues. --- src/content/reference/react/useCallback.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index b9c0c27d2..5693772db 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -103,7 +103,7 @@ function ProductPage({ productId, referrer, theme }) { Zauważyłeś, że przełączanie właściwości `theme` blokuje na chwilę aplikację, ale gdy usuniesz `` z twojego JSX, zauważysz, że znów działa gładko. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. -**Domyślnie, gdy komponent jest ponownie przerenderowywany, React także przerenderowuje rekursywnie wszystkich jego potomków.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli upewniłeś się, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowania, owijając (?) go w [`memo`:](/reference/react/memo) +**Domyślnie, gdy komponent jest ponownie przerenderowywany, React także przerenderowuje rekursywnie wszystkich jego potomków.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli upewniłeś się, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowania, poprzez opakowanie go w [`memo`:](/reference/react/memo) ```js {3,5} import { memo } from 'react'; @@ -155,7 +155,7 @@ function ProductPage({ productId, referrer, theme }) { } ``` -**Owrapowanie (?) `handleSubmit` w `useCallback` zapewnia, że to jest ta *sama* funkcja między przerenderowaniami** (aż do zmiany zależności). Nie *musisz* opakowywać funkcji w `useCallback`, chyba że robisz to z jakiegoś konkretnego powodu. W tym przykładzie powodem jest to, że przekazujesz ją do komponentu owrapowanego (?) w [`memo`,](/reference/react/memo) co pozwala na pominięcie przerenderowania. Istnieją inne powody, dla których możesz potrzebować `useCallback`, opisane dalej na tej stronie. +**Opakowanie `handleSubmit` w `useCallback` zapewnia, że to jest ta *sama* funkcja między przerenderowaniami** (aż do zmiany zależności). Nie *musisz* opakowywać funkcji w `useCallback`, chyba że robisz to z jakiegoś konkretnego powodu. W tym przykładzie powodem jest to, że przekazujesz ją do komponentu opakowanego w [`memo`,](/reference/react/memo) co pozwala na pominięcie przerenderowania. Istnieją inne powody, dla których możesz potrzebować `useCallback`, opisane dalej na tej stronie. @@ -232,8 +232,8 @@ Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze 1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent wrapujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. 1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj nietrwałego (?) stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w bibliotece globalnego stanu. 1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw go zamiast dodawać zapamiętywanie. -1. Unikaj [niepotrzebnych Efektów, które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w Efektach i prowadzą do wielokrotnego przerenderowania komponentów. -1. Staraj się [usunąć niepotrzebne zależności z Efektów.](/learn/removing-effect-dependencies) Na przykład zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do Efektu lub na zewnątrz komponentu. +1. Unikaj [niepotrzebnych efektów, które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w efektach i prowadzą do wielokrotnego przerenderowania komponentów. +1. Postaraj się [usunąć niepotrzebne zależności z efektów.](/learn/removing-effect-dependencies) Na przykład zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do efektu lub na zewnątrz komponentu. Jeśli jakaś interakcja wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najwięcej zyskują na zapamiętywaniu i dodaj zapamiętywanie tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatycznym zapamiętywaniem](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. @@ -694,9 +694,9 @@ W tym przypadku zamiast robienia z `todos` zależność i odczytywania go wewną --- -### Zapobieganie zbyt częstemu wyzwalaniu Efektu {/*preventing-an-effect-from-firing-too-often*/} +### Zapobieganie zbyt częstemu wyzwalaniu efektu {/*preventing-an-effect-from-firing-too-often*/} -Czasami może zdarzyć się, że chcesz wywołać funkcję wewnątrz [Efektu:](/learn/synchronizing-with-effects) +Czasami może zdarzyć się, że chcesz wywołać funkcję wewnątrz [efektu:](/learn/synchronizing-with-effects) ```js {4-9,12} function ChatRoom({ roomId }) { @@ -716,7 +716,7 @@ function ChatRoom({ roomId }) { // ... ``` -To powoduje pewien problem. [Każda reaktywna wartość musi być zadeklarowana jako zależność twojego Efektu.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) Jednak jeśli zadeklarujesz `createOptions` jako zależność, spowoduje to, że twój Efekt będzie ciągle ponawiał łączenie się z pokojem czatowym: +To powoduje pewien problem. [Każda reaktywna wartość musi być zadeklarowana jako zależność twojego efektu.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) Jednak jeśli zadeklarujesz `createOptions` jako zależność, spowoduje to, że twój efekt będzie ciągle ponawiał łączenie się z pokojem czatowym: ```js {6} @@ -729,7 +729,7 @@ To powoduje pewien problem. [Każda reaktywna wartość musi być zadeklarowana // ... ``` -Aby to rozwiązać, możesz owrapować funkcję, którą musisz wywołać z Efektu, za pomocą `useCallback`: +Aby to rozwiązać, możesz opakować funkcję, którą musisz wywołać z efektu, za pomocą `useCallback`: ```js {4-9,16} function ChatRoom({ roomId }) { @@ -751,7 +751,7 @@ function ChatRoom({ roomId }) { // ... ``` -To zapewnia, że funkcja `createOptions` pozostaje taka sama między przerenderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę zależności funkcji.** Przenieś swoją funkcję do *wnętrza* Efektu: +To zapewnia, że funkcja `createOptions` pozostaje taka sama między przerenderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę zależności funkcji.** Przenieś swoją funkcję do *wnętrza* efektu: ```js {5-10,16} function ChatRoom({ roomId }) { @@ -773,7 +773,7 @@ function ChatRoom({ roomId }) { // ... ``` -Teraz twój kod jest prostszy i nie wymaga użycia `useCallback`. [Dowiedz się więcej o usuwaniu zależności Efektu.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect) +Teraz twój kod jest prostszy i nie wymaga użycia `useCallback`. [Dowiedz się więcej o usuwaniu zależności efektu.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect) --- From c550fb6f67fd371f895c0baeefe227b056287b6a Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Tue, 22 Aug 2023 22:19:37 +0200 Subject: [PATCH 08/14] Fix minor translations --- src/content/reference/react/useCallback.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 5693772db..0d194effc 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -230,8 +230,8 @@ Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze **W praktyce możesz uniknąć wielu przypadków zapamiętywania, stosując kilka zasad:** 1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent wrapujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. -1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj nietrwałego (?) stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w bibliotece globalnego stanu. -1. Utrzymuj swoją [logikę renderowania czystą. (?)](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw go zamiast dodawać zapamiętywanie. +1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj chwilowego stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w bibliotece globalnego stanu. +1. Utrzymuj swoją [logikę renderowania czystą.](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw go zamiast dodawać zapamiętywanie. 1. Unikaj [niepotrzebnych efektów, które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w efektach i prowadzą do wielokrotnego przerenderowania komponentów. 1. Postaraj się [usunąć niepotrzebne zależności z efektów.](/learn/removing-effect-dependencies) Na przykład zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do efektu lub na zewnątrz komponentu. @@ -800,7 +800,7 @@ function useRouter() { } ``` -To zapewnia, że konsumenci (?) twojego hooka mogą zoptymalizować swój własny kod, gdy jest to potrzebne. +To zapewnia, że konsumenci twojego hooka mogą zoptymalizować swój własny kod, gdy jest to potrzebne. --- From b59b8500b92d0833ff2b52680da874e6b593042b Mon Sep 17 00:00:00 2001 From: Dawid Sabat Date: Wed, 23 Aug 2023 16:41:46 +0200 Subject: [PATCH 09/14] Fix minor --- src/content/reference/react/useCallback.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 0d194effc..2d3438232 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -50,7 +50,7 @@ Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z pop #### Zastrzeżenia {/*caveats*/} -* `useCallback` jest hookiem, więc można go wywoływać tylko **na głównym poziomie komponentu** lub innego hooka. Nie można go wywołać w pętli lub instrukcji warunkowej. Jeśli masz sytuację, która wymaga pętli lub warunku, stwórz nowy komponent i przenieś do niego ten stan. +* `useCallback` jest hookiem, więc można go wywoływać tylko **na głównym poziomie komponentu** lub innego hooka. Nie można go wywołać w pętli lub instrukcji warunkowej. Jeśli masz sytuację, która wymaga pętli lub warunku, stwórz nowy komponent i przenieś do niego stan. * React **nie odrzuci zapamiętanej funkcji, chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję, gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania. W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens, aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. --- From 6b63ecab2d5de095e548ce5fbf63161faf9429c6 Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 25 Aug 2023 19:44:47 +0200 Subject: [PATCH 10/14] Update src/content/reference/react/useCallback.md Co-authored-by: Jakub Drozdek <30927218+jakubdrozdek@users.noreply.github.com> --- src/content/reference/react/useCallback.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 2d3438232..ebc561770 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -910,7 +910,7 @@ function Report({ item }) { } ``` -Ewentualnie, możesz usunąć `useCallback` z ostatniego fragmentu kodu i zamiast tego owinąć sam komponent `Report` w [`memo`.](/reference/react/memo) Jeśli właściwość `item` się nie zmienia, komponent `Report` pominie przerenderowanie, a zatem komponent `Chart` również pominie przerenderowanie: +Ewentualnie możesz usunąć `useCallback` z ostatniego fragmentu kodu i zamiast tego owinąć sam komponent `Report` w [`memo`.](/reference/react/memo) Jeśli właściwość `item` się nie zmienia, komponent `Report` pominie przerenderowanie, a zatem komponent `Chart` również pominie przerenderowanie: ```js {5,6-8,15} function ReportList({ items }) { From 93c277970d68190217ab7072458c109cc72f6cf3 Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 25 Aug 2023 19:45:12 +0200 Subject: [PATCH 11/14] Update src/content/reference/react/useCallback.md Co-authored-by: Jakub Drozdek <30927218+jakubdrozdek@users.noreply.github.com> --- src/content/reference/react/useCallback.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index ebc561770..a82e5cb56 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -4,7 +4,7 @@ title: useCallback -`useCallback` jest hookiem reactowym, który pozwala na zapamiętywanie (ang. cache, memoize) definicji funkcji pomiędzy przerenderowaniami. +`useCallback` jest hookiem reactowym, który pozwala na zapamiętywanie (*ang.* cache, memoize) definicji funkcji pomiędzy renderowaniami. ```js const cachedFn = useCallback(fn, dependencies) From ae9ab548df159a105caa0bb01fd391cb1ac19ce1 Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 25 Aug 2023 19:45:44 +0200 Subject: [PATCH 12/14] Update src/content/reference/react/useCallback.md Co-authored-by: Jakub Drozdek <30927218+jakubdrozdek@users.noreply.github.com> --- src/content/reference/react/useCallback.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index a82e5cb56..45c6eafcd 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -20,7 +20,7 @@ const cachedFn = useCallback(fn, dependencies) ### `useCallback(fn, dependencies)` {/*usecallback*/} -Wywołaj `useCallback` na głównym poziomie komponentu, aby zapamiętać definicje funkcji pomiędzy przerenderowaniami: +Wywołaj `useCallback` na głównym poziomie komponentu, aby zapamiętać definicje funkcji pomiędzy renderowaniami: ```js {4,9} import { useCallback } from 'react'; From cbf5d09e7bb7d9d68d443eda1bd97ec24e962e26 Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 25 Aug 2023 19:46:29 +0200 Subject: [PATCH 13/14] Update src/content/reference/react/useCallback.md Co-authored-by: Jakub Drozdek <30927218+jakubdrozdek@users.noreply.github.com> --- src/content/reference/react/useCallback.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 45c6eafcd..73b7b0291 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -38,7 +38,7 @@ export default function ProductPage({ productId, referrer, theme }) { #### Parametry {/*parameters*/} -* `fn`: Funkcja, którą chcesz zapamiętać. Może przyjąć dowolne argumenty i zwrócić dowolne wartości. React zwróci (nie wywoła!) twoją funkcję z powrotem w pierwszym renderowaniu. Przy kolejnych renderowaniach, React zwróci ci tę samą funkcję ponownie jeśli lista zależności `dependencies` nie zmieni się od ostatniego renderowania. W przeciwnym razie zwróci ci funkcję, którą przekazałeś podczas obecnego renderowania i zachowa ją do ponownego użycia potem. React nie wywoła twojej funkcji. Funkcja ta zostanie ci zwrócona, abyś mógł sam wybrać gdzie i kiedy ma być wywołana. +* `fn`: Funkcja, którą chcesz zapamiętać. Może przyjąć dowolne argumenty i zwrócić dowolne wartości. React zwróci (nie wywoła!) twoją funkcję z powrotem w pierwszym renderowaniu. Przy kolejnych renderowaniach, React zwróci ci tę samą funkcję ponownie, jeśli lista zależności `dependencies` nie zmieni się od ostatniego renderowania. W przeciwnym razie zwróci ci funkcję, którą przekazano podczas obecnego renderowania i zachowa ją do ponownego użycia. React nie wywoła twojej funkcji. Funkcja ta zostanie ci zwrócona, aby można było samodzielnie wybrać, gdzie i kiedy ma zostać wywołana. * `dependencies`: Lista wszystkich reaktywnych wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała komponentu. Jeżeli twój linter jest [skonfigurowany pod Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). From a48a685b951eeb5dc6890a981b1fc142d1e8fc6d Mon Sep 17 00:00:00 2001 From: Dawid Date: Fri, 25 Aug 2023 20:24:13 +0200 Subject: [PATCH 14/14] Apply suggestions from code review Co-authored-by: Jakub Drozdek <30927218+jakubdrozdek@users.noreply.github.com> --- src/content/reference/react/useCallback.md | 80 +++++++++++----------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index 73b7b0291..4be5786d0 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -40,18 +40,18 @@ export default function ProductPage({ productId, referrer, theme }) { * `fn`: Funkcja, którą chcesz zapamiętać. Może przyjąć dowolne argumenty i zwrócić dowolne wartości. React zwróci (nie wywoła!) twoją funkcję z powrotem w pierwszym renderowaniu. Przy kolejnych renderowaniach, React zwróci ci tę samą funkcję ponownie, jeśli lista zależności `dependencies` nie zmieni się od ostatniego renderowania. W przeciwnym razie zwróci ci funkcję, którą przekazano podczas obecnego renderowania i zachowa ją do ponownego użycia. React nie wywoła twojej funkcji. Funkcja ta zostanie ci zwrócona, aby można było samodzielnie wybrać, gdzie i kiedy ma zostać wywołana. -* `dependencies`: Lista wszystkich reaktywnych wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała komponentu. Jeżeli twój linter jest [skonfigurowany pod Reacta](/learn/editor-setup#linting), sprawdzi on czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i byś zapisana wprost jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). +* `dependencies`: Lista wszystkich reaktywnych wartości użytych w kodzie funkcji `fn`. Reaktywne wartości to właściwości, stan i wszystkie inne zmienne i funkcje zadeklarowane bezpośrednio wewnątrz ciała komponentu. Jeżeli twój linter jest [skonfigurowany pod Reacta](/learn/editor-setup#linting), sprawdzi on, czy każda reaktywna wartość jest poprawnie wskazana jako zależność. Lista zależności musi mieć stałą liczbę elementów i być zapisana w miejscu wywołania, jak np. `[dep1, dep2, dep3]`. React porówna każdą zależność z jej poprzednią wartością używając algorytmu porównania [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). #### Zwracana wartość {/*returns*/} -Podczas pierwszego renderowania, `useCallback` zwróci funkcję `fn`, która została mu przekazana. +Podczas pierwszego renderowania `useCallback` zwróci funkcję `fn`, która została mu przekazana. -Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z poprzedniego renderowania (jeśli zależności nie uległy zmianie) albo zwróci funkcję `fn`, którą przekazałeś podczas tego renderowania. +Podczas kolejnych renderowań zwróci on już zapamiętaną funkcję `fn` z poprzedniego renderowania (jeśli zależności nie uległy zmianie) albo zwróci funkcję `fn`, którą przekazano podczas tego renderowania. #### Zastrzeżenia {/*caveats*/} * `useCallback` jest hookiem, więc można go wywoływać tylko **na głównym poziomie komponentu** lub innego hooka. Nie można go wywołać w pętli lub instrukcji warunkowej. Jeśli masz sytuację, która wymaga pętli lub warunku, stwórz nowy komponent i przenieś do niego stan. -* React **nie odrzuci zapamiętanej funkcji, chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku developerskim React odrzuca zapamiętaną funkcję, gdy komponent jest edytowany. Zarówno w środowisku developerskim jak i w produkcji React odrzuci zapamiętaną funkcję jeśli twój komponent zostaje zawieszony podczas pierwszego montowania. W przyszłości, React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, będzie to miało sens, aby odrzucić zapamiętane funkcje dla elementów, które wyszły poza widoczny obszar zwirtualizowanej tablicy. To powinno sprostać twoim oczekiwaniom jeżeli polegasz na `useCallback` jako optymalizacji wydajności. W innym przypadku, [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents) może być lepsza. +* React **nie odrzuci zapamiętanej funkcji, chyba że istnieje konkretny powód ku temu.** Na przykład, w środowisku deweloperskim React odrzuca zapamiętaną funkcję, gdy komponent jest edytowany. Zarówno w środowisku deweloperskim jak i w produkcji React odrzuci zapamiętaną funkcję, jeśli twój komponent zostaje zawieszony (*ang.* suspended) podczas pierwszego montowania. W przyszłości React może dodać więcej funkcjonalności, które skorzystają z odrzucania zapamiętanej funkcji - na przykład, jeśli React doda w przyszłości wsparcie dla zwirtualizowanych list, uzasadnione będzie odrzucanie zapamiętanych funkcji dla elementów, które wyszły poza widoczny obszar zwirtualizowanej tabeli. Jeśli korzystasz z `useCallback` w celu zoptymalizowania wydajności, powyższe cechy powinny sprostać twoim oczekiwaniom. W innym przypadku lepsza może okazać się [zmienna stanu](/reference/react/useState#im-trying-to-set-state-to-a-function-but-it-gets-called-instead) lub [referencja](/reference/react/useRef#avoiding-recreating-the-ref-contents). --- @@ -59,7 +59,7 @@ Podczas kolejnych renderowań, zwróci on już zapamiętaną funkcję `fn` z pop ### Pomijanie przerenderowywania komponentów {/*skipping-re-rendering-of-components*/} -Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do potomków. Spójrzmy najpierw na składnię jak to zrobić, a potem w jakich przypadkach jest to przydatne. +Gdy optymalizujesz wydajność renderowania, czasem zachodzi potrzeba zapamiętania funkcji, którą przekazujesz do komponentów podrzędnych. Spójrzmy najpierw na składnię, a następnie na listę przypadków, w których może się to przydać. Aby zapamiętać funkcję pomiędzy renderowaniami twojego komponentu, zawrzyj jej definicję w hooku `useCallback`: @@ -76,18 +76,18 @@ function ProductPage({ productId, referrer, theme }) { // ... ``` -Musisz przekazać dwie rzeczy do `useCallback`: +Do `useCallback` musisz przekazać dwie rzeczy: -1. Definicję funkcji, którą chcesz zapamiętać pomiędzy przerenderowaniami. +1. Definicję funkcji, którą chcesz zapamiętać pomiędzy renderowaniami. 2. Listę zależności zawierającą wszystkie wartości wewnątrz komponentu, które są użyte w twojej funkcji. -Przy pierwszym renderowaniu, zwrócona funkcja otrzymana z `useCallback` będzie tą samą, którą przekazałeś. +Przy pierwszym renderowaniu zwrócona funkcja otrzymana z `useCallback` będzie tą samą, którą przekazano do hooka. -Przy następnych renderowaniach, React porówna zależności z zależnościami, które przekazałeś w poprzednim renderowaniu. Jeśli żadna z zależności nie uległa zmianie (porównując z użyciem [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), `useCallback` zwróci tę samą funkcję co poprzednio. W innym wypadku, `useCallback` zwróci funkcję, którą przekazałeś w *tym* renderowaniu. +Przy następnych renderowaniach React porówna zależności z tymi, które przekazano w poprzednim renderowaniu. Jeśli żadna z zależności nie uległa zmianie (porównując z użyciem [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)), `useCallback` zwróci tę samą funkcję co poprzednio. W innym wypadku, `useCallback` zwróci funkcję, którą przekazano w *tym* renderowaniu. -Innymi słowy, `useCallback` zapamięta funkcję pomiędzy przerenderowaniami dopóki zależności się nie zmienią. +Innymi słowy, `useCallback` będzie pamiętać funkcję pomiędzy renderowaniami, dopóki nie zmienią się zależności. -**Posłużmy się przykładem, aby zobaczyć kiedy to może być przydatne.** +**Posłużmy się przykładem, aby zobaczyć, kiedy może się to okazać przydatne.** Załóżmy, że przekazujesz funkcję `handleSubmit` w dół z `ProductPage` do komponentu `ShippingForm`: @@ -101,9 +101,9 @@ function ProductPage({ productId, referrer, theme }) { ); ``` -Zauważyłeś, że przełączanie właściwości `theme` blokuje na chwilę aplikację, ale gdy usuniesz `` z twojego JSX, zauważysz, że znów działa gładko. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. +Twoją uwagę przykuł fakt, iż przełączanie właściwości `theme` blokuje na chwilę aplikację, ale gdy usuniesz `` z kodu JSX, zauważasz, że znów działa płynnie. To pokazuje, że warto jest spróbować zoptymalizować komponent `ShippingForm`. -**Domyślnie, gdy komponent jest ponownie przerenderowywany, React także przerenderowuje rekursywnie wszystkich jego potomków.** Dlatego też, gdy `ProductPage` zostaje przerenderowany z innym `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do przerenderowania. Ale jeśli upewniłeś się, że przerenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął przerenderowanie, gdy jego właściwości są takie same jak podczas ostatniego przerenderowania, poprzez opakowanie go w [`memo`:](/reference/react/memo) +**Domyślnie, gdy komponent jest ponownie renderowywany, React także renderuje rekursywnie wszystkich jego potomków.** Dlatego też, gdy `ProductPage` zostaje wyrenderowany z inną wartością `theme`, komponent `ShippingForm` *również* zostaje przerenderowany. Jest to akceptowalne dla komponentów, które nie wymagają dużo obliczeń do wyrenderowania. Ale jeśli z obserwacji wynika, że ponowne wyrenderowanie trwa długo, można wskazać komponentowi `ShippingForm`, aby pominął renderowanie, gdy jego właściwości są takie same jak podczas ostatniego renderowania, poprzez opakowanie go w [`memo`:](/reference/react/memo) ```js {3,5} import { memo } from 'react'; @@ -113,11 +113,11 @@ const ShippingForm = memo(function ShippingForm({ onSubmit }) { }); ``` -**Po dokonaniu tej zmiany, komponent `ShippingForm` pominie przerenderowanie, jeśli wszystkie jego właściwości są *takie same* jak podczas ostatniego renderowania.** To jest moment, w którym istotne staje się zapamiętywanie funkcji! Załóżmy, że zdefiniowałeś funkcję `handleSubmit` bez użycia hooka `useCallback`: +**Po dokonaniu tej zmiany komponent `ShippingForm` pominie ponowne renderowanie, jeśli wszystkie jego właściwości są *takie same* jak podczas ostatniego renderowania.** To jest moment, w którym istotne staje się zapamiętywanie funkcji! Załóżmy, że zdefiniowaliśmy funkcję `handleSubmit` bez użycia hooka `useCallback`: ```js {2,3,8,12-13} function ProductPage({ productId, referrer, theme }) { - // Za każdym razem, gdy zmienia się theme, to będzie inna funkcja... + // Za każdym razem, gdy zmienia się theme, będzie to inna funkcja... function handleSubmit(orderDetails) { post('/product/' + productId + '/buy', { referrer, @@ -134,11 +134,11 @@ function ProductPage({ productId, referrer, theme }) { } ``` -**W języku JavaScript, `function () {}` lub `() => {}` zawsze tworzy _inną_ funkcję,** podobnie jak literał obiektu `{}` zawsze tworzy nowy obiekt. Zazwyczaj nie byłoby to problemem, ale oznacza to, że właściwości komponentu `ShippingForm` nigdy nie będą takie same i optymalizacja [`memo`](/reference/react/memo) nie zadziała. Tutaj `useCallback` staje się pomocny: +**W języku JavaScript `function () {}` lub `() => {}` zawsze tworzy _inną_ funkcję,** podobnie jak literał obiektu `{}` zawsze tworzy nowy obiekt. Zazwyczaj nie byłoby to problemem, ale oznacza to, że właściwości komponentu `ShippingForm` nigdy nie będą takie same i optymalizacja [`memo`](/reference/react/memo) nie zadziała. Tu z pomocą przychodzi `useCallback`: ```js {2,3,8,12-13} function ProductPage({ productId, referrer, theme }) { - // Powiedz Reactowi, aby zapamiętał twoją funkcję między przerenderowaniami... + // Powiedz Reactowi, aby zapamiętał twoją funkcję między renderowaniami... const handleSubmit = useCallback((orderDetails) => { post('/product/' + productId + '/buy', { referrer, @@ -155,11 +155,11 @@ function ProductPage({ productId, referrer, theme }) { } ``` -**Opakowanie `handleSubmit` w `useCallback` zapewnia, że to jest ta *sama* funkcja między przerenderowaniami** (aż do zmiany zależności). Nie *musisz* opakowywać funkcji w `useCallback`, chyba że robisz to z jakiegoś konkretnego powodu. W tym przykładzie powodem jest to, że przekazujesz ją do komponentu opakowanego w [`memo`,](/reference/react/memo) co pozwala na pominięcie przerenderowania. Istnieją inne powody, dla których możesz potrzebować `useCallback`, opisane dalej na tej stronie. +**Opakowanie `handleSubmit` w `useCallback` zapewnia, że między kolejnymi renderowaniami będzie to ta *sama* funkcja** (aż do zmiany zależności). Nie *musisz* opakowywać funkcji w `useCallback`, chyba że robisz to z jakiegoś konkretnego powodu. W tym przykładzie powodem jest przekazywanie jej do komponentu opakowanego w [`memo`](/reference/react/memo), co pozwala na pominięcie zbędnego renderowania. Inne powody, dla których możesz potrzebować `useCallback`, opisane dalej na tej stronie. -**Powinieneś polegać na `useCallback` tylko jako optymalizacji wydajnościowej.** Jeśli twój kod nie działa bez niego, najpierw znajdź prawdziwą przyczynę problemu i napraw ją. Następnie możesz ponownie dodać `useCallback`. +**Korzystaj z `useCallback` tylko do optymalizacji wydajnościowej.** Jeśli twój kod nie działa bez niego, najpierw znajdź prawdziwą przyczynę problemu i napraw ją. Następnie możesz ponownie dodać `useCallback`. @@ -194,12 +194,12 @@ function ProductPage({ productId, referrer }) { } ``` -Różnica polega na tym *co* pozwalają ci zapamiętać: +Różnica polega na tym, *co* pozwalają ci zapamiętać: -* **[`useMemo`](/reference/react/useMemo) zapamiętuje *wynik* wywołania twojej funkcji.** W tym przykładzie jest to wynik wywołania `computeRequirements(product)`, aby nie zmieniał się, chyba że zmieni się `product`. Pozwala to przekazywać obiekt `requirements` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Gdy będzie to konieczne, React wywoła funkcję, którą przekazałeś podczas renderowania, aby obliczyć wynik. -* **`useCallback` zapamiętuje *samą funkcję*.** W przeciwieństwie do `useMemo`, nie wywołuje dostarczonej funkcji. Zamiast tego zapamiętuje funkcję, którą podałeś, tak aby `handleSubmit` *sam* nie zmieniał się, chyba że zmieni się `productId` lub `referrer`. Pozwala to przekazywać funkcję `handleSubmit` w dół bez niepotrzebnego ponownego przerenderowania `ShippingForm`. Twój kod nie zostanie uruchomiony, dopóki użytkownik nie prześle formularza. +* **[`useMemo`](/reference/react/useMemo) zapamiętuje *wynik* wywołania twojej funkcji.** W tym przykładzie jest to wynik wywołania `computeRequirements(product)`, aby nie zmieniał się, chyba że zmieni się `product`. Pozwala to przekazywać obiekt `requirements` w dół bez niepotrzebnego ponownego renderowania komponentu `ShippingForm`. Gdy będzie to konieczne, React wywoła funkcję, którą przekazano podczas renderowania, aby obliczyć wynik. +* **`useCallback` zapamiętuje *samą funkcję*.** W przeciwieństwie do `useMemo`, nie wywołuje dostarczonej funkcji. Zamiast tego zapamiętuje funkcję, którą mu podamy, tak aby `handleSubmit` *sam* nie zmieniał się, chyba że zmieni się `productId` lub `referrer`. Pozwala to przekazywać funkcję `handleSubmit` w dół bez niepotrzebnego ponownego renderowania komponentu `ShippingForm`. Twój kod nie zostanie uruchomiony, dopóki użytkownik nie prześle formularza. -Jeśli już jesteś zaznajomiony z [`useMemo`,](/reference/react/useMemo) pomocne może być myślenie o `useCallback` w ten sposób: +Jeśli już rozumiesz zasadę działania [`useMemo`,](/reference/react/useMemo), pomocne może być myślenie o `useCallback` w ten sposób: ```js // Uproszczona implementacja (wewnątrz Reacta) @@ -214,7 +214,7 @@ function useCallback(fn, dependencies) { -#### Czy powinieneś używać useCallback wszędzie? {/*should-you-add-usecallback-everywhere*/} +#### Czy należy używać useCallback wszędzie? {/*should-you-add-usecallback-everywhere*/} Jeśli twoja aplikacja jest podobna do tej strony i większość interakcji jest prostych (takich jak zastępowanie strony lub całej sekcji), to zazwyczaj zapamiętywanie nie jest konieczne. Z drugiej strony, jeśli twoja aplikacja przypomina edytor rysunków i większość interakcji jest dość szczegółowa (takie jak przesuwanie kształtów), to możliwe, że zapamiętywanie będzie bardzo pomocne. @@ -229,25 +229,25 @@ Należy zaznaczyć, że `useCallback` nie zapobiega *tworzeniu* funkcji. Zawsze **W praktyce możesz uniknąć wielu przypadków zapamiętywania, stosując kilka zasad:** -1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent wrapujący aktualizuje swój własny stan, React wie, że jego komponenty potomne nie muszą być przerenderowane. +1. Gdy komponent wizualnie zawiera inne komponenty, pozwól mu [przyjmować JSX jako komponenty potomne.](/learn/passing-props-to-a-component#passing-jsx-as-children) Wtedy, jeśli komponent opakowujący zaktualizuje swój własny stan, React będzie wiedzieć, że jego komponenty potomne nie muszą być ponownie wyrenderowane. 1. Preferuj stan lokalny i nie [wynoś stanu wyżej](/learn/sharing-state-between-components) niż to jest konieczne. Nie przechowuj chwilowego stanu, takiego jak formularze czy informacji o tym, czy element został najechany kursorem, na samej górze drzewa komponentów lub w bibliotece globalnego stanu. -1. Utrzymuj swoją [logikę renderowania czystą.](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, to jest błąd w twoim komponencie! Napraw go zamiast dodawać zapamiętywanie. +1. Utrzymuj swoją [logikę renderowania w czystości.](/learn/keeping-components-pure) Jeśli przerenderowanie komponentu powoduje problem lub widoczne wizualne artefakty, błąd tkwi w twoim komponencie! Napraw go, zamiast dodawać memoizację. 1. Unikaj [niepotrzebnych efektów, które aktualizują stan.](/learn/you-might-not-need-an-effect) Większość problemów wydajnościowych w aplikacjach reactowych wynika z serii aktualizacji, które mają swoje źródło w efektach i prowadzą do wielokrotnego przerenderowania komponentów. -1. Postaraj się [usunąć niepotrzebne zależności z efektów.](/learn/removing-effect-dependencies) Na przykład zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do efektu lub na zewnątrz komponentu. +1. Postaraj się [usunąć niepotrzebne zależności z efektów.](/learn/removing-effect-dependencies) Na przykład, zamiast zapamiętywania, często prostsze jest przeniesienie jakiegoś obiektu lub funkcji do efektu lub na zewnątrz komponentu. -Jeśli jakaś interakcja wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najwięcej zyskują na zapamiętywaniu i dodaj zapamiętywanie tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty są łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatycznym zapamiętywaniem](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. +Jeśli jakaś interakcja wciąż działa opornie, [użyj narzędzi do profilowania w narzędziach deweloperskich Reacta](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html), aby zobaczyć, które komponenty najwięcej zyskują na zapamiętywaniu i dodaj zapamiętywanie tam, gdzie jest to potrzebne. Te zasady sprawiają, że twoje komponenty będą łatwiejsze do debugowania i zrozumienia, więc warto się nimi kierować w każdym przypadku. Długoterminowo pracujemy nad [automatycznym zapamiętywaniem](https://www.youtube.com/watch?v=lGEMwh32soc), aby rozwiązać ten problem raz na zawsze. -#### Pomijanie przerenderowania za pomocą `useCallback` i `memo` {/*skipping-re-rendering-with-usecallback-and-memo*/} +#### Zapobieganie ponownego renderowania za pomocą `useCallback` i `memo` {/*skipping-re-rendering-with-usecallback-and-memo*/} -W tym przykładzie komponent `ShippingForm` jest **sztucznie spowolniony**, abyś mógł zobaczyć, co się dzieje, gdy komponent, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. +W tym przykładzie komponent `ShippingForm` jest **sztucznie spowolniony**, abyśmy mogli zobaczyć, co się dzieje, gdy renderowany komponent jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. Zwiększanie licznika wydaje się wolne, ponieważ wymusza przerenderowanie spowolnionego komponentu `ShippingForm`. Jest to oczekiwane, ponieważ licznik się zmienił, więc musisz odzwierciedlić nowy wybór użytkownika na ekranie. -Następnie spróbuj przełączyć motyw. **Dzięki `useCallback` razem z [`memo`](/reference/react/memo), jest to szybkie pomimo sztucznego spowolnienia!** `ShippingForm` pominął przerenderowanie, ponieważ funkcja `handleSubmit` nie zmieniła się. Funkcja `handleSubmit` nie zmieniła się, ponieważ ani `productId`, ani `referrer` (twoje zależności w `useCallback`) nie zmieniły się od ostatniego przerenderowania. +Następnie spróbuj przełączyć motyw. **Dzięki `useCallback` razem z [`memo`](/reference/react/memo), jest to szybkie pomimo sztucznego spowolnienia!** `ShippingForm` pominął przerenderowanie, ponieważ funkcja `handleSubmit` nie zmieniła się. Funkcja `handleSubmit` nie zmieniła się, ponieważ ani `productId`, ani `referrer` (twoje zależności w `useCallback`) nie zmieniły się od ostatniego renderowania. @@ -385,7 +385,7 @@ button[type="button"] { #### Ciągłe przerenderowywanie komponentu {/*always-re-rendering-a-component*/} -W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyś mógł zobaczyć, co się dzieje, gdy komponent reactowy, który renderujesz, jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. +W tym przykładzie implementacja komponentu `ShippingForm` jest również **sztucznie spowolniona**, abyśmy mogli zobaczyć, co się dzieje, gdy renderowany komponent reactowy jest naprawdę wolny. Spróbuj zwiększyć licznik i przełączyć motyw. W przeciwieństwie do poprzedniego przykładu, przełączanie motywu jest teraz również wolne! To dlatego, że **w tej wersji nie ma wywołania `useCallback`,** więc `handleSubmit` jest zawsze nową funkcją, przez co spowolniony komponent `ShippingForm` nie może pominąć przerenderowania. @@ -521,7 +521,7 @@ button[type="button"] { -Natomiast tutaj jest ten sam kod **bez sztucznego spowolnienia.** Czy brak `useCallback` jest tu zauważalny? +Natomiast tutaj mamy ten sam kod **bez sztucznego spowolnienia.** Czy brak `useCallback` jest tu zauważalny? @@ -677,7 +677,7 @@ function TodoList() { // ... ``` -Zazwyczaj powinieneś dążyć do tego, aby zapamiętane funkcje miały jak najmniej zależności. Gdy odczytujesz pewien stan tylko po to, aby obliczyć jego następną wartość, możesz usunąć tę zależność, przekazując zamiast tego [funkcję aktualizującą](/reference/react/useState#updating-state-based-on-the-previous-state): +Zazwyczaj powinniśmy dążyć do tego, aby zapamiętane funkcje miały jak najmniej zależności. Gdy odczytujesz pewien stan tylko po to, aby obliczyć jego następną wartość, możesz usunąć tę zależność, przekazując zamiast tego [funkcję aktualizującą](/reference/react/useState#updating-state-based-on-the-previous-state): ```js {6,7} function TodoList() { @@ -696,7 +696,7 @@ W tym przypadku zamiast robienia z `todos` zależność i odczytywania go wewną ### Zapobieganie zbyt częstemu wyzwalaniu efektu {/*preventing-an-effect-from-firing-too-often*/} -Czasami może zdarzyć się, że chcesz wywołać funkcję wewnątrz [efektu:](/learn/synchronizing-with-effects) +Czasami możesz zechcieć wywołać funkcję wewnątrz [efektu:](/learn/synchronizing-with-effects) ```js {4-9,12} function ChatRoom({ roomId }) { @@ -729,7 +729,7 @@ To powoduje pewien problem. [Każda reaktywna wartość musi być zadeklarowana // ... ``` -Aby to rozwiązać, możesz opakować funkcję, którą musisz wywołać z efektu, za pomocą `useCallback`: +Aby to rozwiązać, możesz opakować funkcję wywoływaną z efektu za pomocą `useCallback`: ```js {4-9,16} function ChatRoom({ roomId }) { @@ -751,7 +751,7 @@ function ChatRoom({ roomId }) { // ... ``` -To zapewnia, że funkcja `createOptions` pozostaje taka sama między przerenderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę zależności funkcji.** Przenieś swoją funkcję do *wnętrza* efektu: +Taka zmiana zapewnia, że funkcja `createOptions` pozostaje taka sama między renderowaniami, jeśli `roomId` jest taki sam. **Jednakże jeszcze lepiej jest usunąć potrzebę używania funkcji jako zależności.** Przenieś swoją funkcję do *wnętrza* efektu: ```js {5-10,16} function ChatRoom({ roomId }) { @@ -808,7 +808,7 @@ To zapewnia, że konsumenci twojego hooka mogą zoptymalizować swój własny ko ### Za każdym razem, gdy mój komponent renderuje się, `useCallback` zwraca inną funkcję {/*every-time-my-component-renders-usecallback-returns-a-different-function*/} -Upewnij się, że podałeś tablicę zależności jako drugi argument! +Upewnij się, że podajesz tablicę zależności jako drugi argument! Jeśli zapomnisz o tablicy zależności, `useCallback` będzie zwracać nową funkcję za każdym razem: @@ -836,7 +836,7 @@ function ProductPage({ productId, referrer }) { // ... ``` -Jeśli to nie pomaga, problem może wynikać z tego, że przynajmniej jedna z twoich zależności zmieniła się od poprzedniego renderowania. Możesz rozwiązać ten problem, dodając ręcznie logowanie twoich zależności do konsoli: +Jeśli to nie pomaga, problem może wynikać z tego, że przynajmniej jedna z twoich zależności zmieniła się od poprzedniego renderowania. Możesz rozwiązać ten problem dodając ręcznie logowanie twoich zależności do konsoli: ```js {5} const handleSubmit = useCallback((orderDetails) => { @@ -854,7 +854,7 @@ Object.is(temp1[1], temp2[1]); // Czy druga zależność jest taka sama między Object.is(temp1[2], temp2[2]); // ... i tak dalej dla każdej zależności ... ``` -Kiedy znajdziesz, która zależność psuje zapamiętywanie, albo znajdź sposób, aby ją usunąć, albo [również ją zapamiętaj.](/reference/react/useMemo#memoizing-a-dependency-of-another-hook) +Kiedy znajdziesz zależność psującą memoizację, znajdź sposób, aby ją usunąć albo [również ją zapamiętaj.](/reference/react/useMemo#memoizing-a-dependency-of-another-hook) ---