From 0c88dd2fd632d93f20b6371245e85c01866b702b Mon Sep 17 00:00:00 2001 From: Jakub Drozdek Date: Tue, 3 Dec 2019 00:36:47 +0100 Subject: [PATCH 1/2] Translate 'Higher-Order Components' page --- content/docs/higher-order-components.md | 206 ++++++++++++------------ 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index a7a123abe..0ab94f687 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -1,32 +1,32 @@ --- id: higher-order-components -title: Higher-Order Components +title: Komponenty wyższego rzędu permalink: docs/higher-order-components.html --- -A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature. +Komponent wyższego rzędu (ang. *Higher-Order Component*), w skrócie KWR (ang. *HOC*), to zaawansowana technika reactowa stosowana w celu wielokrotnego używania logiki komponentu. KWR-y nie są częścią API Reacta *per se*. Są wzorcem, który wyłonił się z kompozycyjnej natury Reacta. -Concretely, **a higher-order component is a function that takes a component and returns a new component.** +Konkretnie rzecz ujmując, **komponent wyższego rzędu jest funkcją, która przyjmuje jako argument inny komponent i zwraca nowy komponent.** ```js const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` -Whereas a component transforms props into UI, a higher-order component transforms a component into another component. +Tak jak zwykły komponent przekształca właściwości (ang. *props*) na fragment UI, tak komponent wyższego rzędu przekształca komponent w inny komponent. -HOCs are common in third-party React libraries, such as Redux's [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) and Relay's [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html). +KWR-y pojawiają się często w zewnętrznych bibliotekach reactowych, np. [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) w Reduksie czy [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) w Relayu. -In this document, we'll discuss why higher-order components are useful, and how to write your own. +W tym artykule podejmiemy dyskusję o tym, dlaczego komponenty wyższego rzędu są użyteczne oraz jak napisać własny. -## Use HOCs For Cross-Cutting Concerns {#use-hocs-for-cross-cutting-concerns} +## Używaj KWR-ów do problemów przekrojowych {#use-hocs-for-cross-cutting-concerns} -> **Note** +> **Uwaga** > -> We previously recommended mixins as a way to handle cross-cutting concerns. We've since realized that mixins create more trouble than they are worth. [Read more](/blog/2016/07/13/mixins-considered-harmful.html) about why we've moved away from mixins and how you can transition your existing components. +> Poprzednio do rozwiązywania problemów przekrojowych sugerowaliśmy korzystanie z mixinów. Zdaliśmy sobie jednak sprawę, iż wprowadzają one więcej zamieszania niż pożytku. [Przeczytaj ten artykuł](/blog/2016/07/13/mixins-considered-harmful.html), jeśli chcesz dowiedzieć się, dlaczego odeszliśmy od tego wzorca i w jaki sposób dostosować swoje istniejące komponenty. -Components are the primary unit of code reuse in React. However, you'll find that some patterns aren't a straightforward fit for traditional components. +Komponenty to podstawowa jednostka wielokrotnie używalnego kodu reactowego. Jednak niektóre wzorce nie pasują idealnie do tradycyjnego zastosowania komponentów. -For example, say you have a `CommentList` component that subscribes to an external data source to render a list of comments: +Dla przykładu, powiedzmy, że mamy komponent `CommentList`, który subskrybuje się do zewnętrznego źródła danych i renderuje listę komentarzy: ```js class CommentList extends React.Component { @@ -34,23 +34,23 @@ class CommentList extends React.Component { super(props); this.handleChange = this.handleChange.bind(this); this.state = { - // "DataSource" is some global data source + // "DataSource" jest jakimś globalnym źródłem danych comments: DataSource.getComments() }; } componentDidMount() { - // Subscribe to changes + // Zasubskrybuj się na zmiany DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { - // Clean up listener + // Usuń subskrypcję DataSource.removeChangeListener(this.handleChange); } handleChange() { - // Update component state whenever the data source changes + // Zaktualizuj stan komponentu przy każdej zmianie danych źródłowych this.setState({ comments: DataSource.getComments() }); @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Later, you write a component for subscribing to a single blog post, which follows a similar pattern: +Później możesz chcieć napisać komponent subskrybujący się na pojedynczy wpis na blogu, w którym zastosujesz podobny wzorzec: ```js class BlogPost extends React.Component { @@ -100,15 +100,15 @@ class BlogPost extends React.Component { } ``` -`CommentList` and `BlogPost` aren't identical — they call different methods on `DataSource`, and they render different output. But much of their implementation is the same: +Komponenty `CommentList` i `BlogPost` nie są identyczne — wywołują bowiem inne metody `DataSource` i renderują inny fragment interfejsu. Jednak spora część ich implementacji jest taka sama: -- On mount, add a change listener to `DataSource`. -- Inside the listener, call `setState` whenever the data source changes. -- On unmount, remove the change listener. +- Po zamontowaniu komponentu subskrybują się w `DataSource`. +- Wewnątrz funkcji nasłuchującej wywołują `setState` przy każdej zmianie danych źródłowych. +- Po odmontowaniu komponentu usuwają subskrypcję. -You can imagine that in a large app, this same pattern of subscribing to `DataSource` and calling `setState` will occur over and over again. We want an abstraction that allows us to define this logic in a single place and share it across many components. This is where higher-order components excel. +Można sobie wyobrazić, że w większej aplikacji co rusz będziemy pisać podobny kod, który subskrybuje się w `DataSource` i wywołuje `setState`. Chcielibyśmy zbudować warstwę abstrakcji, która pozwoliłaby nam zdefiniować tę logikę w jednym miejscu i współdzielić ją w wielu komponentach. Tu do akcji wkraczają komponenty wyższego rzędu. -We can write a function that creates components, like `CommentList` and `BlogPost`, that subscribe to `DataSource`. The function will accept as one of its arguments a child component that receives the subscribed data as a prop. Let's call the function `withSubscription`: +Możemy napisać funkcję, tworzącą komponenty takie jak `CommentList` czy `BlogPost`, która subskrybuje się w `DataSource`. Funkcja ta jako jeden z argumentów będzie przyjmować komponent potomny, który otrzyma zasubskrybowane dane poprzez określoną właściwość (ang. *prop*). Nazwijmy tę funkcję `withSubscription`: ```js const CommentListWithSubscription = withSubscription( @@ -122,14 +122,14 @@ const BlogPostWithSubscription = withSubscription( ); ``` -The first parameter is the wrapped component. The second parameter retrieves the data we're interested in, given a `DataSource` and the current props. +Pierwszy z argumentów to opakowywany komponent. Drugi, po otrzymaniu `DataSource` i aktualnych właściwości komponentu, wyciąga interesujące nas dane ze źródła. -When `CommentListWithSubscription` and `BlogPostWithSubscription` are rendered, `CommentList` and `BlogPost` will be passed a `data` prop with the most current data retrieved from `DataSource`: +Gdy `CommentListWithSubscription` i `BlogPostWithSubscription` zostaną wyrenderowane, do `CommentList` i `BlogPost` trafi właściwość `data`, zawierająca aktualne dane ze źródła `DataSource`: ```js -// This function takes a component... +// Ta funkcja przyjmuje jako argument pewien komponent... function withSubscription(WrappedComponent, selectData) { - // ...and returns another component... + // ...i zwraca inny komponent... return class extends React.Component { constructor(props) { super(props); @@ -140,7 +140,7 @@ function withSubscription(WrappedComponent, selectData) { } componentDidMount() { - // ... that takes care of the subscription... + // ... który zajmuje się podpięciem subskrypcji... DataSource.addChangeListener(this.handleChange); } @@ -155,83 +155,83 @@ function withSubscription(WrappedComponent, selectData) { } render() { - // ... and renders the wrapped component with the fresh data! - // Notice that we pass through any additional props + // ... i renderuje opakowywany komponent z aktualnymi danymi! + // Zauważ, że dodatkowo przekazujemy tu też pozostałe właściwości return ; } }; } ``` -Note that a HOC doesn't modify the input component, nor does it use inheritance to copy its behavior. Rather, a HOC *composes* the original component by *wrapping* it in a container component. A HOC is a pure function with zero side-effects. +Zwróć uwagę, że KWR nie modyfikuje przekazanego mu komponentu ani nie stosuje dziedziczenia w celu skopiowania jego zachowania. Zamiast tego *wkomponowuje* przekazany komponent poprzez jego *opakowanie* w kontener. KWR jest zatem czystą funkcją (ang. *pure function*), nie mającą żadnych efektów ubocznych. -And that's it! The wrapped component receives all the props of the container, along with a new prop, `data`, which it uses to render its output. The HOC isn't concerned with how or why the data is used, and the wrapped component isn't concerned with where the data came from. +I to by było na tyle! Opakowany komponent otrzyma wszystkie właściwości kontenera, a dodatkowo `data`, używaną do wyrenderowania interfejsu. Dla KWR-a nie ma znaczenia, w jaki sposób wykorzystywane są dane, a z kolei opakowywany komponent nie przejmuje się tym, skąd te dane pochodzą. -Because `withSubscription` is a normal function, you can add as many or as few arguments as you like. For example, you may want to make the name of the `data` prop configurable, to further isolate the HOC from the wrapped component. Or you could accept an argument that configures `shouldComponentUpdate`, or one that configures the data source. These are all possible because the HOC has full control over how the component is defined. +Z racji tego, że `withSubscription` jest zwykłą funkcją, możesz przekazać jej tyle argumentów, ile uważasz za stosowne. Możesz, na przykład, zechcieć definiować nazwę dla właściwości `data`, żeby jeszcze bardziej odizolować KWR od opakowanego komponentu. Możesz też przekazać argument, który steruje metodą `shouldComponentUpdate` lub taki, który konfiguruje w jakiś sposób źródło danych. To wszystko jest możliwe dlatego, że KWR ma pełną kontrolę nad opakowywanym komponentem. -Like components, the contract between `withSubscription` and the wrapped component is entirely props-based. This makes it easy to swap one HOC for a different one, as long as they provide the same props to the wrapped component. This may be useful if you change data-fetching libraries, for example. +Podobnie jak w przypadku zwykłych komponentów, kontrakt pomiędzy `withSubscription` i opakowywanym komponentem w całości opiera się na właściwościach. Pozwala to na łatwą podmianę jednego KWR-a na inny, pod warunkiem że przekazują one renderowanemu komponentowi takie same właściwości. Może się to okazać przydatne np. w razie potrzeby podmiany biblioteki pobierającej dane. -## Don't Mutate the Original Component. Use Composition. {#dont-mutate-the-original-component-use-composition} +## Nie modyfikuj opakowywanego komponentu. Użyj kompozycji. {#dont-mutate-the-original-component-use-composition} -Resist the temptation to modify a component's prototype (or otherwise mutate it) inside a HOC. +Powstrzymaj się przed wszelkimi zmianami prototypu komponentu (innymi słowy, przed jego mutowaniem) wewnątrz KWR-a. ```js function logProps(InputComponent) { InputComponent.prototype.componentWillReceiveProps = function(nextProps) { - console.log('Current props: ', this.props); - console.log('Next props: ', nextProps); + console.log('Aktualne właściwości: ', this.props); + console.log('Nowe właściwości: ', nextProps); }; - // The fact that we're returning the original input is a hint that it has - // been mutated. + // Fakt, że zwracamy tu oryginalny komponent, może świadczyć o tym, + // że został on w jakiś sposób zmodyfikowany. return InputComponent; } -// EnhancedComponent will log whenever props are received +// EnhancedComponent wypisze na konsolę informację przy każdej zmianie właściwości komponentu const EnhancedComponent = logProps(InputComponent); ``` -There are a few problems with this. One is that the input component cannot be reused separately from the enhanced component. More crucially, if you apply another HOC to `EnhancedComponent` that *also* mutates `componentWillReceiveProps`, the first HOC's functionality will be overridden! This HOC also won't work with function components, which do not have lifecycle methods. +Z powyższym kodem jest kilka problemów. Po pierwsze, nie można ponownie użyć opakowywanego komponentu osobno, w innym miejscu aplikacji. Co ważne, jeśli zaaplikujesz kolejny `EnhancedComponent`, który *także* zmienia metodę `componentWillReceiveProps`, funkcjonalność pierwszego KWR-a zostanie nadpisana! Ponadto, ten KWR nie zadziała poprawnie z komponentami funkcyjnymi, ponieważ nie mają one metod cyklu życia. -Mutating HOCs are a leaky abstraction—the consumer must know how they are implemented in order to avoid conflicts with other HOCs. +KWR-y mutujące są swego rodzaju "dziurawą abstrakcją" - konsument takiego komponentu musi znać jego implementację, aby uniknąć konfliktów z innymi KWR-ami. -Instead of mutation, HOCs should use composition, by wrapping the input component in a container component: +Zamiast modyfikować, KWR-y powinny komponować poprzez opakowywanie otrzymanego komponentu w kontener: ```js function logProps(WrappedComponent) { return class extends React.Component { componentWillReceiveProps(nextProps) { - console.log('Current props: ', this.props); - console.log('Next props: ', nextProps); + console.log('Aktualne właściwości: ', this.props); + console.log('Nowe właściwości: ', nextProps); } render() { - // Wraps the input component in a container, without mutating it. Good! + // Opakowuje otrzymany komponent w kontener, bez jego zmieniania. Dobrze! return ; } } } ``` -This HOC has the same functionality as the mutating version while avoiding the potential for clashes. It works equally well with class and function components. And because it's a pure function, it's composable with other HOCs, or even with itself. +Powyższy KWR ma podobną funkcjonalność co wersja modyfikująca komponent, lecz nie wprowadza dodatkowych "zgrzytów". Działa zarówno z komponentami klasowymi, jak i funkcyjnymi. A ponieważ jest napisany jako czysta funkcja (ang. *pure function*), można go komponować z innymi KWR-ami, czy nawet z nim samym. -You may have noticed similarities between HOCs and a pattern called **container components**. Container components are part of a strategy of separating responsibility between high-level and low-level concerns. Containers manage things like subscriptions and state, and pass props to components that handle things like rendering UI. HOCs use containers as part of their implementation. You can think of HOCs as parameterized container component definitions. +Być może udało ci się zauważyć pewne podobieństwa pomiędzy KWR-ami a wzorcem zwanym **komponenty-kontenery**. Komponenty-kontenery wchodzą w skład strategii oddzielającej odpowiedzialności na niskim i wysokim poziomie abstrakcji. Kontenery zarządzają takimi rzeczami jak subskrypcje czy stan, a także przekazują właściwości do komponentów, które z kolei zajmują się renderowaniem interfejsu. KWR-y używają kontenerów w części swojej implementacji. Można by powiedzieć, że KWR-y to takie definicje sparametryzowanych komponentów-kontenerów. -## Convention: Pass Unrelated Props Through to the Wrapped Component {#convention-pass-unrelated-props-through-to-the-wrapped-component} +## Konwencja: Przekazuj nieużywane właściwości do opakowywanego komponentu {#convention-pass-unrelated-props-through-to-the-wrapped-component} -HOCs add features to a component. They shouldn't drastically alter its contract. It's expected that the component returned from a HOC has a similar interface to the wrapped component. +KWR-y dodają jakąś funkcjonalność do komponentu. Nie powinny jednak zmieniać zbyt drastycznie jego kontraktu. Oczekuje się, że komponent zwracany przez KWR będzie miał podobny interfejs do oryginalnego. -HOCs should pass through props that are unrelated to its specific concern. Most HOCs contain a render method that looks something like this: +KWR-y powinny przekazywać dalej właściwości, które nie są przez nie używane. Większość KWR-ów zawiera metodę renderującą podobną do tej poniżej: ```js render() { - // Filter out extra props that are specific to this HOC and shouldn't be - // passed through + // Odfiltruj wszelkie dodatkowe właściwości, które są używane przez KWR + // i nie powinny być przekazywane dalej const { extraProp, ...passThroughProps } = this.props; - // Inject props into the wrapped component. These are usually state values or - // instance methods. + // Wstrzyknij właściwości w opakowywany komponent. Zazwyczaj będą to + // wartości stanu lub metody instancji. const injectedProp = someStateOrInstanceMethod; - // Pass props to wrapped component + // Przekaż właściwości do renderowanego komponentu return ( Component`. Functions whose output type is the same as its input type are really easy to compose together. +Taka forma może wydawać się niejasna czy nawet niepotrzebna, ale ma jedną praktyczną własność. Jednoargumentowe KWR-y, takie jak ten zwrócony przez `connect` w powyższym przykładzie, mają sygnaturę `Component => Component`. Funkcje, których typ wartości zwracanej jest taki sam, jak typ wartości wejściowej, bardzo łatwo dają się komponować. ```js -// Instead of doing this... +// Zamiast robić tak... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) -// ... you can use a function composition utility -// compose(f, g, h) is the same as (...args) => f(g(h(...args))) +// ... możesz użyć pomocniczej funkcji komponującej +// compose(f, g, h) daje to samo, co (...args) => f(g(h(...args))) const enhance = compose( - // These are both single-argument HOCs + // Obydwie poniższe funkcje są jednoargumentowymi KWR-ami withRouter, connect(commentSelector) ) const EnhancedComponent = enhance(WrappedComponent) ``` -(This same property also allows `connect` and other enhancer-style HOCs to be used as decorators, an experimental JavaScript proposal.) +(Ta sama własność pozwala również funkcji `connect`, jak i innym KWR-om napisanym w stylu "funkcji wzbogacających" (ang. *enhancer*), występować w formie dekoratora - eksperymentalnej funkcjonalności proponowanej dla JavaScriptu.) -The `compose` utility function is provided by many third-party libraries including lodash (as [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose), and [Ramda](https://ramdajs.com/docs/#compose). +Funkcja pomocnicza `compose` jest dostarczana przez wiele bibliotek zewnętrznych, wliczając w to `lodash` (jako [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [`Redux`](https://redux.js.org/api/compose) czy [Ramda](https://ramdajs.com/docs/#compose). -## Convention: Wrap the Display Name for Easy Debugging {#convention-wrap-the-display-name-for-easy-debugging} +## Konwencja: Opakowuj wyświetlaną nazwę dla łatwiejszego debuggowania {#convention-wrap-the-display-name-for-easy-debugging} -The container components created by HOCs show up in the [React Developer Tools](https://github.com/facebook/react-devtools) like any other component. To ease debugging, choose a display name that communicates that it's the result of a HOC. +Komponenty-kontenery stworzone przez KWR-y wyglądają w narzędziu [React Developer Tools](https://github.com/facebook/react-devtools) jak zwykłe komponenty. Aby ułatwić sobie debugowanie, możesz zmienić wyświetlaną nazwę na inną, informującą o tym, że jest to wynik działania KWR-a. -The most common technique is to wrap the display name of the wrapped component. So if your higher-order component is named `withSubscription`, and the wrapped component's display name is `CommentList`, use the display name `WithSubscription(CommentList)`: +Najczęściej stosowaną techniką jest opakowywanie wyświetlanej nazwy (ang. *display name*) renderowanego komponentu. Jeśli więc twój komponent wyższego rzędu nazywa się `withSubscription`, a opakowywany komponent to `CommentList`, użyj nazwy `WithSubscription(CommentList)`: ```js function withSubscription(WrappedComponent) { @@ -314,60 +314,60 @@ function getDisplayName(WrappedComponent) { ``` -## Caveats {#caveats} +## Zastrzeżenia {#caveats} -Higher-order components come with a few caveats that aren't immediately obvious if you're new to React. +Z komponentami wyższego rzędu wiążą się pewne restrykcje, które mogą nie być oczywiste dla początkujących reactowców. -### Don't Use HOCs Inside the render Method {#dont-use-hocs-inside-the-render-method} +### Nie używaj KWR-ów wewnątrz metody render {#dont-use-hocs-inside-the-render-method} -React's diffing algorithm (called reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from `render` is identical (`===`) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they're not equal, the previous subtree is unmounted completely. +Algorytm różnicujący w Reakcie (zwany "rekonsyliacyjnym") korzysta z tożsamości komponentu, aby stwierdzić, czy powinien zaktualizować istniejące poddrzewo, czy też wyrzucić je do kosza i stworzyć nowe. Jeśli komponent zwracany przez funkcję `render` jest identyczny (`===`) jak komponent z poprzedniego renderowania, React aktualizuje drzewo rekurencyjnie, porównując je z tym nowym. Jeśli są różne, poprzednie poddrzewo jest odmontowywane w całości. -Normally, you shouldn't need to think about this. But it matters for HOCs because it means you can't apply a HOC to a component within the render method of a component: +W innych przypadkach nie powinno cię to za bardzo obchodzić. Ma to jednak znaczenie dla KWR-ów, ponieważ oznacza to, że nie możesz stworzyć KWR-a wewnątrz metody `render` innego komponentu: ```js render() { - // A new version of EnhancedComponent is created on every render + // Przy każdym renderowaniu tworzona jest nowa wersja komponentu EnhancedComponent // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); - // That causes the entire subtree to unmount/remount each time! + // Powoduje to każdorazowe odmontowanie i ponowne zamontowanie całego poddrzewa! return ; } ``` -The problem here isn't just about performance — remounting a component causes the state of that component and all of its children to be lost. +Problemem nie jest tu sama wydajność aplikacji. Ponowne montowanie komponentu powoduje utratę jego stanu i wszystkich jego potomków. -Instead, apply HOCs outside the component definition so that the resulting component is created only once. Then, its identity will be consistent across renders. This is usually what you want, anyway. +Zamiast tego używaj KWR-ów na zewnątrz definicji komponentu, tak żeby powstały komponent został stworzony tylko raz. Dzięki temu jego tożsamość zostanie zachowana pomiędzy kolejnymi renderowaniami. A zwykle o to właśnie chodzi. -In those rare cases where you need to apply a HOC dynamically, you can also do it inside a component's lifecycle methods or its constructor. +W szczególnych przypadkach, gdy musisz użyć KWR-a dynamicznie, możesz zrobić to wewnątrz metody cyklu życia komponentu lub w jego konstruktorze. -### Static Methods Must Be Copied Over {#static-methods-must-be-copied-over} +### Pamiętaj o skopiowaniu metod statycznych {#static-methods-must-be-copied-over} -Sometimes it's useful to define a static method on a React component. For example, Relay containers expose a static method `getFragment` to facilitate the composition of GraphQL fragments. +Czasami przydatne okazuje się zdefiniowanie metody statycznej dla komponentu reactowego. Przykładowo, kontenery biblioteki Relay udostępniają statyczną metodę `getFragment`, ułatwiającą komponowanie fragmentów GraphQLowych. -When you apply a HOC to a component, though, the original component is wrapped with a container component. That means the new component does not have any of the static methods of the original component. +Kiedy używasz KWR-a na komponencie, oryginalny komponent jest opakowywany w komponent-kontener. Oznacza to, że nowy komponent nie otrzyma żadnej z metod statycznych oryginalnego komponentu. ```js -// Define a static method +// Definiujemy metodę statyczną WrappedComponent.staticMethod = function() {/*...*/} -// Now apply a HOC +// Używamy KWR-a const EnhancedComponent = enhance(WrappedComponent); -// The enhanced component has no static method +// Rozszerzony komponent nie posiada metody statycznej typeof EnhancedComponent.staticMethod === 'undefined' // true ``` -To solve this, you could copy the methods onto the container before returning it: +Można sobie z tym poradzić kopiując metody do kontenera przed jego zwróceniem: ```js function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} - // Must know exactly which method(s) to copy :( + // Musi wiedzieć, jakie metody trzeba skopiować :( Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; } ``` -However, this requires you to know exactly which methods need to be copied. You can use [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics) to automatically copy all non-React static methods: +Niestety wymaga to przewidzenia, jakie metody będą musiały być skopiowane. Możesz jednak użyć [hoist-non-react-statics](https://github.com/mridgway/hoist-non-react-statics), aby automatycznie skopiować wszystkie nie-reactowe metody statyczne: ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -378,22 +378,22 @@ function enhance(WrappedComponent) { } ``` -Another possible solution is to export the static method separately from the component itself. +Innym możliwym rozwiązaniem jest wyeksportowanie statycznej metody komponentu niezależnie od niego. ```js -// Instead of... +// Zamiast... MyComponent.someFunction = someFunction; export default MyComponent; -// ...export the method separately... +// ...wyeksportuj metodę osobno... export { someFunction }; -// ...and in the consuming module, import both +// ...a w module korzystającym z nich, zaimportuj obydwie rzeczy import MyComponent, { someFunction } from './MyComponent.js'; ``` -### Refs Aren't Passed Through {#refs-arent-passed-through} +### Referencje nie są przekazywane {#refs-arent-passed-through} -While the convention for higher-order components is to pass through all props to the wrapped component, this does not work for refs. That's because `ref` is not really a prop — like `key`, it's handled specially by React. If you add a ref to an element whose component is the result of a HOC, the ref refers to an instance of the outermost container component, not the wrapped component. +Mimo że powszechną konwencją jest przekazywanie w KWR-ach wszystkich właściwości w dół do opakowywanego komponentu, nie działa to z referencjami. Dzieje się tak dlatego, że `ref` nie jest zwykłą właściwością — podobnie jak `key`, jest traktowana inaczej przez Reacta. Jeśli dodasz referencję do elementu, którego wynikiem renderowania jest komponent opakowany przez KWR, referencja będzie odnosiła się do instancji najbardziej zewnętrznego komponentu-kontenera, a nie do komponentu opakowywanego. -The solution for this problem is to use the `React.forwardRef` API (introduced with React 16.3). [Learn more about it in the forwarding refs section](/docs/forwarding-refs.html). +Rozwiązaniem tego problemu jest użycie interfejsu `React.forwardRef` (wprowadzonego w Reakcie 16.3). [Więcej o tym mechanizmie dowiesz się z rozdziału o przekazywaniu referencji](/docs/forwarding-refs.html). From a6c27bb5ca6a149668d0b63a52dced3c4b0aa741 Mon Sep 17 00:00:00 2001 From: Jakub Drozdek Date: Wed, 4 Dec 2019 21:22:55 +0100 Subject: [PATCH 2/2] Apply suggestions from PR --- content/docs/higher-order-components.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 0ab94f687..debbbac78 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -16,13 +16,13 @@ Tak jak zwykły komponent przekształca właściwości (ang. *props*) na fragmen KWR-y pojawiają się często w zewnętrznych bibliotekach reactowych, np. [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) w Reduksie czy [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) w Relayu. -W tym artykule podejmiemy dyskusję o tym, dlaczego komponenty wyższego rzędu są użyteczne oraz jak napisać własny. +W tym artykule wyjaśnimy, dlaczego komponenty wyższego rzędu są użyteczne oraz jak napisać własny. ## Używaj KWR-ów do problemów przekrojowych {#use-hocs-for-cross-cutting-concerns} > **Uwaga** > -> Poprzednio do rozwiązywania problemów przekrojowych sugerowaliśmy korzystanie z mixinów. Zdaliśmy sobie jednak sprawę, iż wprowadzają one więcej zamieszania niż pożytku. [Przeczytaj ten artykuł](/blog/2016/07/13/mixins-considered-harmful.html), jeśli chcesz dowiedzieć się, dlaczego odeszliśmy od tego wzorca i w jaki sposób dostosować swoje istniejące komponenty. +> Dawniej do rozwiązywania problemów przekrojowych sugerowaliśmy korzystanie z mixinów. Zdaliśmy sobie jednak sprawę, iż wprowadzają one więcej zamieszania niż pożytku. [Przeczytaj ten artykuł](/blog/2016/07/13/mixins-considered-harmful.html), jeśli chcesz dowiedzieć się, dlaczego odeszliśmy od tego wzorca i w jaki sposób dostosować swoje istniejące komponenty. Komponenty to podstawowa jednostka wielokrotnie używalnego kodu reactowego. Jednak niektóre wzorce nie pasują idealnie do tradycyjnego zastosowania komponentów. @@ -361,7 +361,7 @@ Można sobie z tym poradzić kopiując metody do kontenera przed jego zwrócenie ```js function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} - // Musi wiedzieć, jakie metody trzeba skopiować :( + // Musimy wiedzieć, jakie metody trzeba skopiować :( Enhance.staticMethod = WrappedComponent.staticMethod; return Enhance; }