diff --git a/content/docs/context.md b/content/docs/context.md index b16c5d7c2..83e0b3790 100644 --- a/content/docs/context.md +++ b/content/docs/context.md @@ -1,61 +1,61 @@ --- id: context -title: Context +title: Kontekst permalink: docs/context.html --- -Context provides a way to pass data through the component tree without having to pass props down manually at every level. +Kontekst umożliwia przekazywanie danych wewnątrz drzewa komponentów bez konieczności przekazywania ich przez właściwości każdego komponentu pośredniego. -In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree. +W typowej aplikacji reactowej dane przekazywane są z góry w dół (od rodzica do dziecka) poprzez właściwości. Może się to jednak okazać zbyt uciążliwe w przypadku niektórych danych (np. preferencje językowe, schemat UI czy paleta kolorów), z których korzystają komponenty na wielu poziomach struktury. Konteksty umożliwiają współdzielenie pewnych wartości przez takie komponenty bez konieczności przekazywania ich jako właściwości na każdym poziomie drzewa. -- [When to Use Context](#when-to-use-context) -- [Before You Use Context](#before-you-use-context) -- [API](#api) +- [Kiedy należy użyć kontekstu?](#when-to-use-context) +- [Zanim użyjesz kontekstu](#before-you-use-context) +- [Interfejs API](#api) - [React.createContext](#reactcreatecontext) - [Context.Provider](#contextprovider) - [Class.contextType](#classcontexttype) - [Context.Consumer](#contextconsumer) - [Context.displayName](#contextdisplayname) -- [Examples](#examples) - - [Dynamic Context](#dynamic-context) - - [Updating Context from a Nested Component](#updating-context-from-a-nested-component) - - [Consuming Multiple Contexts](#consuming-multiple-contexts) -- [Caveats](#caveats) -- [Legacy API](#legacy-api) +- [Przykłady](#examples) + - [Kontekst dynamiczny](#dynamic-context) + - [Aktualizacja kontekstu z komponentu zagnieżdżonego](#updating-context-from-a-nested-component) + - [Odczyt z kilku kontekstów jednocześnie](#consuming-multiple-contexts) +- [Zastrzeżenia](#caveats) +- [Przestarzały interfejs API](#legacy-api) -## When to Use Context {#when-to-use-context} +## Kiedy należy użyć kontekstu? {#when-to-use-context} -Context is designed to share data that can be considered "global" for a tree of React components, such as the current authenticated user, theme, or preferred language. For example, in the code below we manually thread through a "theme" prop in order to style the Button component: +Konteksty zaprojektowano do współdzielenia danych, które można uznać za "globalne" dla drzewa komponentów, takich jak informacje o zalogowanym użytkowniku, schemat kolorów czy preferowany język. W poniższym przykładzie wartość `theme`, potrzebną do ostylowania przycisku, przekazujemy ręcznie: `embed:context/motivation-problem.js` -Using context, we can avoid passing props through intermediate elements: +W pomocą kontekstu moglibyśmy uniknąć przekazywania jej na każdym poziomie struktury: `embed:context/motivation-solution.js` -## Before You Use Context {#before-you-use-context} +## Zanim użyjesz kontekstu {#before-you-use-context} -Context is primarily used when some data needs to be accessible by *many* components at different nesting levels. Apply it sparingly because it makes component reuse more difficult. +Zwykle kontekstu używa się w sytuacjach, w których pewne dane muszą być dostępne dla *wielu* komponentów na różnych poziomach zagnieżdżenia. Korzystaj jednak z tego mechanizmu z rozwagą, ponieważ utrudnia on wielokrotne używanie komponentów zależnych. -**If you only want to avoid passing some props through many levels, [component composition](/docs/composition-vs-inheritance.html) is often a simpler solution than context.** +**Jeśli twoim celem jest wyłącznie uniknięcie przekazywania wartości przez kilka poziomów drzewa, zwykle łatwiejszym i lepszym rozwiązaniem okazuje się [kompozycja komponentów](/docs/composition-vs-inheritance.html).** -For example, consider a `Page` component that passes a `user` and `avatarSize` prop several levels down so that deeply nested `Link` and `Avatar` components can read it: +Rozważmy komponent `Page`, który musi przekazać właściwości `user` oraz `avatarSize` kilka poziomów w dół, tak aby głęboko zagnieżdżone komponenty `Link` i `Avatar` mogły je odczytać: ```js -// ... which renders ... +// ... który renderuje... -// ... which renders ... +// ... który renderuje... -// ... which renders ... +// ... który renderuje... ``` -It might feel redundant to pass down the `user` and `avatarSize` props through many levels if in the end only the `Avatar` component really needs it. It's also annoying that whenever the `Avatar` component needs more props from the top, you have to add them at all the intermediate levels too. +Przekazywanie tych wartości przez tyle poziomów, tylko po to by mógł je odczytać `Avatar`, wydaje się lekką przesadą. Dodatkowo, gdyby `Avatar` w pewnym momencie zaczął wymagać jeszcze jednej wartości z góry, należałoby ją również przekazać przez te wszystkie poziomy. -One way to solve this issue **without context** is to [pass down the `Avatar` component itself](/docs/composition-vs-inheritance.html#containment) so that the intermediate components don't need to know about the `user` or `avatarSize` props: +Jednym z rozwiązań tego problemu **bez używania kontekstów** jest [przekazanie w dół samego komponentu `Avatar`](/docs/composition-vs-inheritance.html#containment), dzięki czemu komponenty pośrednie nie muszą niczego wiedzieć o właściwościach `user` czy `avatarSize`: ```js function Page(props) { @@ -68,21 +68,21 @@ function Page(props) { return ; } -// Now, we have: +// Teraz mamy: -// ... which renders ... +// ... który renderuje... -// ... which renders ... +// ... który renderuje... -// ... which renders ... +// ... który renderuje... {props.userLink} ``` -With this change, only the top-most Page component needs to know about the `Link` and `Avatar` components' use of `user` and `avatarSize`. +Dzięki takiej zmianie tylko komponent `Page`, znajdujący się najwyżej w hierarchii, musi wiedzieć o tym, że `Link` i `Avatar` zależą od wartości `user` i `avatarSize`. -This *inversion of control* can make your code cleaner in many cases by reducing the amount of props you need to pass through your application and giving more control to the root components. However, this isn't the right choice in every case: moving more complexity higher in the tree makes those higher-level components more complicated and forces the lower-level components to be more flexible than you may want. +Takie "odwrócenie sterowania" (ang. *inversion of control*) sprawia, że kod staje się czytelniejszy poprzez zmniejszenie liczby wartości przeplecionych przez strukturę aplikacji, jak również daje większą kontrolę komponentom znajdującym się wysoko w hierarchii. Należy jednak pamiętać, że to podejście nie zawsze jest najlepszym rozwiązaniem. Przeniesienie złożoności w górę hierarchii sprawia, że komponenty na górze stają się bardziej złożone, a także wymusza często nadmierną elastyczność na komponentach poniżej. -You're not limited to a single child for a component. You may pass multiple children, or even have multiple separate "slots" for children, [as documented here](/docs/composition-vs-inheritance.html#containment): +Warto zwrócić uwagę, że dany komponent nie jest ograniczony do posiadania tylko jednego potomka. Poprzez właściwości do komponentu możemy przekazać wielu potomków naraz lub stworzyć kilka oddzielnych "slotów" dla poszczególnych potomków, [jak opisano to w tym rozdziale](/docs/composition-vs-inheritance.html#containment): ```js function Page(props) { @@ -104,11 +104,11 @@ function Page(props) { } ``` -This pattern is sufficient for many cases when you need to decouple a child from its immediate parents. You can take it even further with [render props](/docs/render-props.html) if the child needs to communicate with the parent before rendering. +Takie podejście jest wystarczające w większości przypadków, gdy pojawia się konieczność oddzielenia potomka od jego bezpośrednich przodków. Można pójść jeszcze o krok dalej i skorzystać z wzorca [właściwości renderujących (ang. *render props*)](/docs/render-props.html), jeśli chcemy, by potomek przed wyrenderowaniem mógł skomunikować się z rodzicem. -However, sometimes the same data needs to be accessible by many components in the tree, and at different nesting levels. Context lets you "broadcast" such data, and changes to it, to all components below. Common examples where using context might be simpler than the alternatives include managing the current locale, theme, or a data cache. +Czasami jednak te same dane muszą być dostępne dla wielu komponentów w drzewie, na wielu różnych poziomach struktury. Konteksty pozwalają na "rozgłoszenie" (ang. *broadcast*) zarówno samych danych, jak i wszelkich ich modyfikacji, do komponentów znajdujących się poniżej w hierarchii. Używanie kontekstów, zamiast pozostałych wzorców, zwykle sprawdza się przy zarządzaniu aktualnym językiem lub motywem, a także przy przechowywaniu danych we wspólnej pamięci podręcznej. -## API {#api} +## Interfejs API {#api} ### `React.createContext` {#reactcreatecontext} @@ -116,27 +116,27 @@ However, sometimes the same data needs to be accessible by many components in th const MyContext = React.createContext(defaultValue); ``` -Creates a Context object. When React renders a component that subscribes to this Context object it will read the current context value from the closest matching `Provider` above it in the tree. +Tworzy obiekt kontekstu. Gdy React renderuje komponent, który zasubskrybował się do tego kontekstu, będzie przekazywać mu aktualną wartość z najbliższego "dostawcy" (`Provider`) powyżej w drzewie. -The `defaultValue` argument is **only** used when a component does not have a matching Provider above it in the tree. This can be helpful for testing components in isolation without wrapping them. Note: passing `undefined` as a Provider value does not cause consuming components to use `defaultValue`. +Argument `defaultValue` jest używany **tylko** gdy komponent odczytujący z kontekstu nie ma nad sobą żadnego dostawcy. Przydaje się to podczas testowania komponentów w izolacji, ponieważ nie ma konieczności opakowywania ich w sztucznych dostawców. Uwaga: przekazanie dostawcy wartości `undefined` nie spowoduje, że zasubskrybowane komponenty otrzymają wartość z argumentu `defaultValue`. ### `Context.Provider` {#contextprovider} ```js - + ``` -Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes. +Każdy obiekt kontekstu posiada własny komponent dostawcy (ang. *provider*), który pozwala komponentom odczytującym na zasubskrybowanie się na zmiany w tym kontekście. -Accepts a `value` prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree. +Wartość przekazana we właściwości `value` będzie trafiała do "konsumentów" (ang. *consumer*) tego kontekstu znajdujących się poniżej w drzewie. Jeden dostawca może być połączony z wieloma konsumentami. Zagnieżdżanie dostawców jeden pod drugim powoduje nadpisanie wartości kontekstu w danym poddrzewie. -All consumers that are descendants of a Provider will re-render whenever the Provider's `value` prop changes. The propagation from Provider to its descendant consumers is not subject to the `shouldComponentUpdate` method, so the consumer is updated even when an ancestor component bails out of the update. +Wszyscy konsumenci znajdujący się poniżej dostawcy będą ponownie renderowani przy każdej zmianie właściwości `value`. Propagacja od dostawcy do jego podległych konsumentów nie jest brana pod uwagę przez metodę `shouldComponentUpdate`, a co za tym idzie, konsumenci będą renderowani ponownie nawet jeśli ich przodkowie nie zostali przerenderowani. -Changes are determined by comparing the new and old values using the same algorithm as [`Object.is`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description). +Zmiany są wykrywane poprzez porównanie starej i nowej wartości przy użyciu algorytmu podobnego do [`Object.is`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description). -> Note +> Uwaga > -> The way changes are determined can cause some issues when passing objects as `value`: see [Caveats](#caveats). +> Sposób, w jaki wykrywane są zmiany, może powodować problemy przy przekazywaniu do `value` obiektów (zob. ["Zastrzeżenia"](#caveats)). ### `Class.contextType` {#classcontexttype} @@ -144,7 +144,7 @@ Changes are determined by comparing the new and old values using the same algori class MyClass extends React.Component { componentDidMount() { let value = this.context; - /* perform a side-effect at mount using the value of MyContext */ + /* wykonaj akcję podczas montowania z użyciem aktualnej wartości z MyContext */ } componentDidUpdate() { let value = this.context; @@ -156,19 +156,19 @@ class MyClass extends React.Component { } render() { let value = this.context; - /* render something based on the value of MyContext */ + /* wyrenderuj coś przy użyciu aktualnej wartości z MyContext */ } } MyClass.contextType = MyContext; ``` -The `contextType` property on a class can be assigned a Context object created by [`React.createContext()`](#reactcreatecontext). This lets you consume the nearest current value of that Context type using `this.context`. You can reference this in any of the lifecycle methods including the render function. +Do właściwości `contextType` w komponencie klasowym można przypisać obiekt kontekstu utworzony przy pomocy funkcji [`React.createContext()`](#reactcreatecontext). Dzięki temu wartość najbliższego kontekstu tego typu jest dostępna pod zmienną `this.context`. Możesz odwoływać się do tej wartości w każdej z metod cyklu życia komponentu, łącznie z metodą renderującą. -> Note: +> Uwaga: > -> You can only subscribe to a single context using this API. If you need to read more than one see [Consuming Multiple Contexts](#consuming-multiple-contexts). +> Za pomocą tego interfejsu można zasubskrybować się tylko do jednego kontekstu. Jeśli chcesz połączyć się z wieloma kontekstami, zajrzyj do sekcji pt. ["Odczyt z kilku kontekstów jednocześnie"](#consuming-multiple-contexts). > -> If you are using the experimental [public class fields syntax](https://babeljs.io/docs/plugins/transform-class-properties/), you can use a **static** class field to initialize your `contextType`. +> Jeśli korzystasz z eksperymentalnej [składni publicznych pól klasy](https://babeljs.io/docs/plugins/transform-class-properties/), do inicjalizacji `contextType` możesz użyć pola statycznego, oznaczonego przez **static**. ```js @@ -176,7 +176,7 @@ class MyClass extends React.Component { static contextType = MyContext; render() { let value = this.context; - /* render something based on the value */ + /* wyrenderuj coś na podstawie aktualnej wartości */ } } ``` @@ -185,37 +185,37 @@ class MyClass extends React.Component { ```js - {value => /* render something based on the context value */} + {value => /* wyrenderuj coś na podstawie wartości z kontekstu */} ``` -A React component that subscribes to context changes. This lets you subscribe to a context within a [function component](/docs/components-and-props.html#function-and-class-components). +Komponent reactowy, który subskrybuje się na zmiany w kontekście. Pozwala na nasłuchiwanie zmian z wnętrza [komponentu funkcyjnego](/docs/components-and-props.html#function-and-class-components). -Requires a [function as a child](/docs/render-props.html#using-props-other-than-render). The function receives the current context value and returns a React node. The `value` argument passed to the function will be equal to the `value` prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the `value` argument will be equal to the `defaultValue` that was passed to `createContext()`. +Jego [potomkiem musi być funkcja](/docs/render-props.html#using-props-other-than-render). Funkcja ta otrzymuje aktualną wartość z kontekstu i zwraca węzeł reactowy. Argument `value` przekazany do tej funkcji będzie równy właściwości `value` najbliższego dostawcy tego kontekstu powyżej w drzewie. Jeśli ponad komponentem nie ma żadnego dostawcy, zostanie użyta wartość `defaultValue` przekazana do `createContext()`. -> Note +> Uwaga > -> For more information about the 'function as a child' pattern, see [render props](/docs/render-props.html). +> Aby dowiedzieć się więcej na temat wzorca "funkcji przekazanej jako potomek", zajrzyj do rozdziału o [właściwościach renderujących](/docs/render-props.html). ### `Context.displayName` {#contextdisplayname} -Context object accepts a `displayName` string property. React DevTools uses this string to determine what to display for the context. +Obiekt kontekstu przyjmuje atrybut tekstowy `displayName`. Jest on używany przez React DevTools do wyświetlenia nazwy kontekstu. -For example, the following component will appear as MyDisplayName in the DevTools: +Na przykład, poniższy komponent wyświetli się w narzędziach deweloperskich jako "MyDisplayName": ```js{2} -const MyContext = React.createContext(/* some value */); +const MyContext = React.createContext(/* jakaś wartość */); MyContext.displayName = 'MyDisplayName'; - // "MyDisplayName.Provider" in DevTools - // "MyDisplayName.Consumer" in DevTools + // "MyDisplayName.Provider" w DevTools + // "MyDisplayName.Consumer" w DevTools ``` -## Examples {#examples} +## Przykłady {#examples} -### Dynamic Context {#dynamic-context} +### Kontekst dynamiczny {#dynamic-context} -A more complex example with dynamic values for the theme: +Bardziej złożony przykład korzystający z dynamicznej wartości dla motywu: **theme-context.js** `embed:context/theme-detailed-theme-context.js` @@ -226,9 +226,9 @@ A more complex example with dynamic values for the theme: **app.js** `embed:context/theme-detailed-app.js` -### Updating Context from a Nested Component {#updating-context-from-a-nested-component} +### Aktualizacja kontekstu z komponentu zagnieżdżonego {#updating-context-from-a-nested-component} -It is often necessary to update the context from a component that is nested somewhere deeply in the component tree. In this case you can pass a function down through the context to allow consumers to update the context: +Często pojawia się potrzeba zaktualizowania kontekstu z komponentu znajdującego się gdzieś głęboko w drzewie. W takim wypadku należy przez kontekst przekazać funkcję, za pomocą której konsumenci będą mogli go aktualizować: **theme-context.js** `embed:context/updating-nested-context-context.js` @@ -239,28 +239,27 @@ It is often necessary to update the context from a component that is nested some **app.js** `embed:context/updating-nested-context-app.js` -### Consuming Multiple Contexts {#consuming-multiple-contexts} +### Odczyt z kilku kontekstów jednocześnie {#consuming-multiple-contexts} -To keep context re-rendering fast, React needs to make each context consumer a separate node in the tree. +Aby zapewnić szybkość ponownego renderowania kontekstu, React musi stworzyć w drzewie osobny węzeł dla każdego konsumenta. `embed:context/multiple-contexts.js` -If two or more context values are often used together, you might want to consider creating your own render prop component that provides both. +Jeśli często używasz dwóch lub więcej wartości z różnych kontekstów, sugerujemy stworzyć oddzielny komponent z właściwością renderującą (ang. *render prop*), który dostarcza je wszystkie. -## Caveats {#caveats} +## Zastrzeżenia {#caveats} -Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider's parent re-renders. For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for `value`: +Kontekst podczas decydowania, co należy ponownie wyrenderować, sprawdza tożsamość referencji. Z tego powodu w niektórych przypadkach ponowne wyrenderowanie rodzica dostawcy kontekstu może skutkować niechcianym powtórnym wyrenderowaniem wszystkich konsumentów danego kontekstu. W poniższym przykładzie dzieje się tak, ponieważ obiekt przekazywany do właściwości `value` dla dostawcy kontekstu jest za każdym razem tworzony na nowo: `embed:context/reference-caveats-problem.js` - -To get around this, lift the value into the parent's state: +Aby temu zapobiec, wystarczy przenieść tę wartość do stanu rodzica: `embed:context/reference-caveats-solution.js` -## Legacy API {#legacy-api} +## Przestarzały interfejs API {#legacy-api} -> Note +> Uwaga > -> React previously shipped with an experimental context API. The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. The legacy API will be removed in a future major React version. Read the [legacy context docs here](/docs/legacy-context.html). +> React poprzednio był wyposażony w eksperymentalny interfejs API dla kontekstów. Mimo iż jest on przestarzały, będzie wspierany we wszystkich wersjach 16.x, jednak aplikacje powinny dążyć do migracji na nową wersję. Przestarzały interfejs zostanie usunięty w kolejnej głównej wersji Reacta. Aby dowiedzieć się więcej na ten temat, [przeczytaj dokumentację przestarzałego kontekstu](/docs/legacy-context.html). diff --git a/examples/context/motivation-problem.js b/examples/context/motivation-problem.js index d166f400a..7c738b6fc 100644 --- a/examples/context/motivation-problem.js +++ b/examples/context/motivation-problem.js @@ -6,10 +6,10 @@ class App extends React.Component { function Toolbar(props) { // highlight-range{1-4,7} - // The Toolbar component must take an extra "theme" prop - // and pass it to the ThemedButton. This can become painful - // if every single button in the app needs to know the theme - // because it would have to be passed through all components. + // Komponent `Toolbar` musi przyjmować dodatkową właściwość "theme" + // i przekazywać ją w dół do `ThemedButton`. Gdyby każdy przycisk w aplikacji + // wymagał dostępu do tej wartości, mogłoby to okazać się uciążliwe, + // ponieważ należałoby przekazywać ją przez wszystkie poziomy struktury. return (
diff --git a/examples/context/motivation-solution.js b/examples/context/motivation-solution.js index 94c6030a9..629546a41 100644 --- a/examples/context/motivation-solution.js +++ b/examples/context/motivation-solution.js @@ -1,15 +1,15 @@ // highlight-range{1-4} -// Context lets us pass a value deep into the component tree -// without explicitly threading it through every component. -// Create a context for the current theme (with "light" as the default). +// Kontekst pozwala na przekazywanie wartości głęboko do drzewa komponentów +// z pominięciem komponentów pośrednich. +// Stwórzmy kontekst dla aktualnie wybranego motywu (nadając mu domyślną wartość "light" - jasny). const ThemeContext = React.createContext('light'); class App extends React.Component { render() { // highlight-range{1-3,5} - // Use a Provider to pass the current theme to the tree below. - // Any component can read it, no matter how deep it is. - // In this example, we're passing "dark" as the current value. + // Użyj "dostawcy" (Provider), aby ustawić motyw dla tego poddrzewa aplikacji. + // Każdy komponent będzie mógł go odczytać, nie ważne jak głęboko w drzewie się znajduje. + // W tym przykładzie ustawiamy motyw na "dark" - ciemny. return ( @@ -19,8 +19,8 @@ class App extends React.Component { } // highlight-range{1,2} -// A component in the middle doesn't have to -// pass the theme down explicitly anymore. +// Komponent pośredni nie musi już jawnie przekazywać tego ustawienia +// w dół hierarchii. function Toolbar(props) { return (
@@ -31,9 +31,9 @@ function Toolbar(props) { class ThemedButton extends React.Component { // highlight-range{1-3,6} - // Assign a contextType to read the current theme context. - // React will find the closest theme Provider above and use its value. - // In this example, the current theme is "dark". + // Przypisz wartość do `contextType`, aby odczytać aktualne ustawienie motywu z kontekstu. + // React znajdzie najbliższego dostawcę (Provider) motywu i użyje jego wartości. + // W tym przykładzie aktualny motyw będzie ciemny ("dark"). static contextType = ThemeContext; render() { return )}