From 6852c0dd5ce3500016bfb55e2debfb24812988a0 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab Date: Tue, 10 Dec 2019 14:20:03 +0200 Subject: [PATCH 01/43] Page Higher-Order Components has been translated. --- content/docs/higher-order-components.md | 197 ++++++++++++------------ 1 file changed, 98 insertions(+), 99 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index a7a123abe..1a55e68cd 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: Компоненти вищого порядку 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. +Компонент вищого порядку (Higher-Order Component, HOC) — це просунута техніка для повторного використання логіки компоненту. Сам по собі HOC не є частиною React API, але через композиційну природу компонентів він є розповсюдженним патерном проектування. -Concretely, **a higher-order component is a function that takes a component and returns a new component.** +Тобто, **компонент вищого порядку — це функція, яка приймає компонент та повертає новий компонент.** ```js const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` -Whereas a component transforms props into UI, a higher-order component transforms a component into another component. +Якщо звичайний компонент перетворює props у UI, то компонент вищого порядку перетворює один компонент на інший. -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). +HOC поширені у сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. -In this document, we'll discuss why higher-order components are useful, and how to write your own. +У цьому розділі мі обговоримо чому компоненти вищого порядку корисні та як створювати власні. -## Use HOCs For Cross-Cutting Concerns {#use-hocs-for-cross-cutting-concerns} +## Використання HOC для перехресної функціональності {#use-hocs-for-cross-cutting-concerns} -> **Note** +> **Примітка** > -> 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. +> Раніше ми рекомендували міксині для реалізації перехресної функціональности. Але с часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. -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. +Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак ви побачите, що вони не є відповідним рішенням для ряду проблем. -For example, say you have a `CommentList` component that subscribes to an external data source to render a list of comments: +Наприклад, ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: ```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" є деяким глобальним джерелом даних comments: DataSource.getComments() }; } componentDidMount() { - // Subscribe to changes + // Підписка на зміни DataSource.addChangeListener(this.handleChange); } componentWillUnmount() { - // Clean up listener + // Відписка DataSource.removeChangeListener(this.handleChange); } handleChange() { - // Update component state whenever the data source changes + // Оновлення стану компонента, коли у джерелі даних відбулись зміни 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: +Пізніше, ви описуєте компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: ```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: +`CommentList` та `BlogPost` не є ідентичними — вони викликають різні методи `DataSource` та вони відображають різний UI. Однак значна частина їх реалізації збігається: -- On mount, add a change listener to `DataSource`. -- Inside the listener, call `setState` whenever the data source changes. -- On unmount, remove the change listener. +- Після монтування вони підписуються на зміни у `DataSource`. +- Викликають `setState`, коли у джерелі даних відбуваються зміни. +- При розмонтуванні відписуються від `DataSource`. -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. +Чи можете Ви уявити, що у великому додатку ця схема підписки буде виникати знову й знову? Нам потрібна абстракція, яка дозволить визначити цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречні компоненти вищого порядку. -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`: +Ми можемо написати функцію, що створює компоненти, як `CommentList` чи `BlogPost`, які підписуються на `DataSource`. В якості одного з аргументів функція буде приймати дочірній компонент, який отримає дані з підписки у якості власного prop. Назвімо цю функцію `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. +Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` й props, та вилучає потрібні нам дані. -When `CommentListWithSubscription` and `BlogPostWithSubscription` are rendered, `CommentList` and `BlogPost` will be passed a `data` prop with the most current data retrieved from `DataSource`: +Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості prop з найактуальнішими даними отриманими від `DataSource`: ```js -// This function takes a component... +// Ця функція отримує компонент ... function withSubscription(WrappedComponent, selectData) { - // ...and returns another component... + // ... та повертає інший компонент ... return class extends React.Component { constructor(props) { super(props); @@ -140,7 +140,7 @@ function withSubscription(WrappedComponent, selectData) { } componentDidMount() { - // ... that takes care of the subscription... + // ... тут відбувається підписка ... DataSource.addChangeListener(this.handleChange); } @@ -155,25 +155,25 @@ function withSubscription(WrappedComponent, selectData) { } render() { - // ... and renders the wrapped component with the fresh data! - // Notice that we pass through any additional props + // ... та відображується обгорнутий компонент зі свіжими даними! + // Зверніть увагу, що ми перадаємо усі props 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. +Зверніть увагу на те, що HOC не модифікує отриманий компонент та не наслідує його поведінку. Швидше, HOC створює *композицію*, *обгортаючи* оригінальний компонент у контейнер. HOC є чистою функцією без побічних ефектів. -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. +От і все! Обгорнутий компонент отримує всі props, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. -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. +Оскільки `withSubscription` це звичайна функція, ви можете додати стільки аргументів, скільки забажаєте. Наприклад, ви вирішили зробити ім’я параметру `data` конфігуруємим, щоби додатково ізолювати HOC від обгорнутого компонента. Або Ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. -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. +Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один HOC на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. -## Don't Mutate the Original Component. Use Composition. {#dont-mutate-the-original-component-use-composition} +## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} -Resist the temptation to modify a component's prototype (or otherwise mutate it) inside a HOC. +Втримайтеся від бажання змінити прототип компонента (або мутуваті його іншим чином) всередині HOC. ```js function logProps(InputComponent) { @@ -181,20 +181,19 @@ function logProps(InputComponent) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); }; - // The fact that we're returning the original input is a hint that it has - // been mutated. + // Якщо ми повертаємо лише той самий отриманий компонент - це натяк, що він був мутований return InputComponent; } -// EnhancedComponent will log whenever props are received +// EnhancedComponent буде щоразу друкувати в консоль, коли отримає новий prop 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. +З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо Ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. -Mutating HOCs are a leaky abstraction—the consumer must know how they are implemented in order to avoid conflicts with other HOCs. +Мутуючи HOC є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими HOC. -Instead of mutation, HOCs should use composition, by wrapping the input component in a container component: +Замість мутації, HOC мають реалізовувати композицію, обгортаючи переданий компонент у контейнер: ```js function logProps(WrappedComponent) { @@ -204,34 +203,33 @@ function logProps(WrappedComponent) { console.log('Next props: ', nextProps); } render() { - // Wraps the input component in a container, without mutating it. Good! + // Обгорайте переданий компонент у контейнер, не мутуючи його! 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. +Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама с собою. -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. +Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальности між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси й внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. -## Convention: Pass Unrelated Props Through to the Wrapped Component {#convention-pass-unrelated-props-through-to-the-wrapped-component} +## Конвенція: передавайте сторонні props обгорненому компоненту {#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. +HOC додає компоненту функціональність. Він не повинен змінювати його початкове призначення. Очікується, що повернений HOC компонент буде мати інтерфейс аналогічний обгорнутому. -HOCs should pass through props that are unrelated to its specific concern. Most HOCs contain a render method that looks something like this: +HOC повинні передавати ті props, що не пов'язані з їх функціональністю, у незмінному стані. Більшість компонентів вищого порядку мають рендер-метод, схожий на цей: ```js render() { - // Filter out extra props that are specific to this HOC and shouldn't be - // passed through + // Відфільтруйте зайві props, що характерні для HOC та не мають потрапити до компонента const { extraProp, ...passThroughProps } = this.props; - // Inject props into the wrapped component. These are usually state values or - // instance methods. + // Створіть ін’єкцію для обгорнутого компонента. + // Зазвичай це значення стану або методи екземпляра const injectedProp = someStateOrInstanceMethod; - // Pass props to wrapped component + // Передайте props до обгорнутого компонента return ( Component`. Functions whose output type is the same as its input type are really easy to compose together. +Іншими словами, `connect` - це функція вищого порядку, яка повертає компонент вищого порядку! + +Ця форма може здатися заплутаною або непотрібною, але вона має корисну властивість. Одноаргументні HOC, як і той, який повертається функцією `connect`, мають підпис `Component => Component`. Функції, з однаковим типом результату та єдиного аргументу, легко поєднуються у композицію. ```js -// Instead of doing this... +// Замість цього ... 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))) +// ... Ви можете використати композиційну функцію +// compose(f, g, h) теж саме, що (...args) => f(g(h(...args))) const enhance = compose( - // These are both single-argument HOCs + // Обидва параметра є HOC та приймають лише один аргумент 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.) +(Саме ця властивість дозволяє використовувати `connect` та інші поширюючи функціональність HOC у якості експериментальних JavaScript декораторів.) -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). +Ви можете знайти допоміжну функцію `compose` у багатьох сторонніх бібліотеках, включаючи lodash (під назвою [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose) та [Ramda](https://ramdajs.com/docs/#compose). -## Convention: Wrap the Display Name for Easy Debugging {#convention-wrap-the-display-name-for-easy-debugging} +## Конвенція: повертайте ім’я обгорнутого компонента для полегшення процессу {#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. +Створений HOC компонент-контейнер відображається в [React Develper Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат HOC. -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)`: +Найпоширеніший прийом - обгортати відображуване ім’я загорнутого компонента. Отже, якщо ваш компонент вищого порядку названий `withSubscription`, а відображене ім’я загорнутого компонента - `CommentList`, визначте відображуване ім'я як `WithSubscription(CommentList)`: ```js function withSubscription(WrappedComponent) { @@ -314,60 +312,61 @@ function getDisplayName(WrappedComponent) { ``` -## Caveats {#caveats} +## Застереження {#caveats} -Higher-order components come with a few caveats that aren't immediately obvious if you're new to React. +Якщо Ви лише починаєте використовувати React, то варто повідомити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. -### Don't Use HOCs Inside the render Method {#dont-use-hocs-inside-the-render-method} +### Не використовуйте HOC у середині рендер-методів {#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. +Алгоритм порівняння React, що відомий як reconciliation (або узгодження), використовує перевірку на тотожність компонента, щоб визначити, чи слід оновити існуюче піддерево компонентів або слід знищити його та змонтувати нове. Якщо компонент, що був повернений рендер-методом, ідентичний (`===`) попередньому результату, React рекурсивно оновлює піддерева, порівнюючи його з новим. Якщо вони не тотожні, то попереднє піддерево буде повністю розмонтовано. -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: +Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що Ви не можете застосувати HOC до компонента в рендер-методі іншого компонента: ```js render() { - // A new version of EnhancedComponent is created on every render + // Під час кожного виклику рендер-методу створюється новий екземпляр EnhancedComponent // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); - // That causes the entire subtree to unmount/remount each time! + // Це призводить до того, що все піддерево щоразу перераховується! 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. +Проблема тут полягає не лише в продуктивності — повторне перерахування компонента втрачає стан цього компонента та всіх його потомків. + +Замість цього застосовуйте HOC за межами визначення компонента, щоб отриманий компонент був створений лише один раз. У цьому випадку React буде порівнювати один і той же компонент при повторному виклику рендер-метода. -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. +У тих рідкісних випадках, коли вам потрібно динамічно застосовувати HOC, Ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. -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. -### Static Methods Must Be Copied Over {#static-methods-must-be-copied-over} +### Копіюйте статичні методи {#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. +Іноді буває корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. -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. +Якщо Ви застосовуєте HOC, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. ```js -// Define a static method +// Визначте статичний метод WrappedComponent.staticMethod = function() {/*...*/} -// Now apply a HOC +// Тепер застосуйте HOC const EnhancedComponent = enhance(WrappedComponent); -// The enhanced component has no static method +// EnhancedComponent не має статичного методу typeof EnhancedComponent.staticMethod === 'undefined' // true ``` -To solve this, you could copy the methods onto the container before returning it: +Вам необхідно скопіювати методи до того, як повернути новий компонент, щоб вирішити цю проблему: ```js function enhance(WrappedComponent) { class Enhance extends React.Component {/*...*/} - // Must know exactly which method(s) to copy :( + // Потрібно точно знати, який метод(и) скопіювати :( 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: +На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів Ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -378,22 +377,22 @@ function enhance(WrappedComponent) { } ``` -Another possible solution is to export the static method separately from the component itself. +Ще одне можливе рішення — експортувати статичні методи окремо від компонента. ```js -// Instead of... +// Замість цього ... MyComponent.someFunction = someFunction; export default MyComponent; -// ...export the method separately... +// ... експортуйте метод окремо ... export { someFunction }; -// ...and in the consuming module, import both +// ... в модулі-споживачі ми можемо імпортувати обидва import MyComponent, { someFunction } from './MyComponent.js'; ``` -### Refs Aren't Passed Through {#refs-arent-passed-through} +### Refs не передаються {#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. +Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, й тому інакше оброблюється React. Якщо Ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. -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). +Розв’язання цієї проблеми є використання API `React.forwardRef` (введений з React 16.3). [Дізнайтеся більше про це в розділі Переадресація рефів](/docs/forwarding-refs.html). From 95f70013549cc86f55927380bd15339e001270b9 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab Date: Thu, 12 Dec 2019 16:00:24 +0200 Subject: [PATCH 02/43] Edited article's translation. --- content/docs/higher-order-components.md | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 1a55e68cd..11994ebf8 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -4,7 +4,7 @@ title: Компоненти вищого порядку permalink: docs/higher-order-components.html --- -Компонент вищого порядку (Higher-Order Component, HOC) — це просунута техніка для повторного використання логіки компоненту. Сам по собі HOC не є частиною React API, але через композиційну природу компонентів він є розповсюдженним патерном проектування. +Компонент вищого порядку (Higher-Order Component, HOC) — це просунута технологія для повторного використання логіки компоненту. Сам по собі HOC не є частиною React API, але через композиційну природу компонентів він є розповсюдженним патерном проектування. Тобто, **компонент вищого порядку — це функція, яка приймає компонент та повертає новий компонент.** @@ -14,15 +14,15 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); Якщо звичайний компонент перетворює props у UI, то компонент вищого порядку перетворює один компонент на інший. -HOC поширені у сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. +HOC поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. -У цьому розділі мі обговоримо чому компоненти вищого порядку корисні та як створювати власні. +У цьому розділі ми обговоримо чому компоненти вищого порядку корисні та як створювати власні. ## Використання HOC для перехресної функціональності {#use-hocs-for-cross-cutting-concerns} > **Примітка** > -> Раніше ми рекомендували міксині для реалізації перехресної функціональности. Але с часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. +> Раніше ми рекомендували міксині для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак ви побачите, що вони не є відповідним рішенням для ряду проблем. @@ -104,11 +104,11 @@ class BlogPost extends React.Component { - Після монтування вони підписуються на зміни у `DataSource`. - Викликають `setState`, коли у джерелі даних відбуваються зміни. -- При розмонтуванні відписуються від `DataSource`. +- При демонтуванні вони відписуються від `DataSource`. Чи можете Ви уявити, що у великому додатку ця схема підписки буде виникати знову й знову? Нам потрібна абстракція, яка дозволить визначити цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречні компоненти вищого порядку. -Ми можемо написати функцію, що створює компоненти, як `CommentList` чи `BlogPost`, які підписуються на `DataSource`. В якості одного з аргументів функція буде приймати дочірній компонент, який отримає дані з підписки у якості власного prop. Назвімо цю функцію `withSubscription`: +Ми можемо написати функцію, що створює компоненти, як `CommentList` чи `BlogPost`, які підписуються на `DataSource`. В якості одного з аргументів функція буде приймати дочірній компонент, який отримає дані з підписки у якості власного prop. Назвемо цю функцію `withSubscription`: ```js const CommentListWithSubscription = withSubscription( @@ -124,7 +124,7 @@ const BlogPostWithSubscription = withSubscription( Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` й props, та вилучає потрібні нам дані. -Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості prop з найактуальнішими даними отриманими від `DataSource`: +Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості prop з найактуальнішими даними, отриманими від `DataSource`: ```js // Ця функція отримує компонент ... @@ -156,7 +156,7 @@ function withSubscription(WrappedComponent, selectData) { render() { // ... та відображується обгорнутий компонент зі свіжими даними! - // Зверніть увагу, що ми перадаємо усі props + // Зверніть увагу, що ми передаємо усі props return ; } }; @@ -210,11 +210,11 @@ function logProps(WrappedComponent) { } ``` -Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама с собою. +Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама з собою. -Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальности між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси й внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. +Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси й внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. -## Конвенція: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} +## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} HOC додає компоненту функціональність. Він не повинен змінювати його початкове призначення. Очікується, що повернений HOC компонент буде мати інтерфейс аналогічний обгорнутому. @@ -239,9 +239,9 @@ render() { } ``` -Ця конвенція допомагає забезпечити максимальну гнучкість та можливість повторного використання HOC. +Ця угода допомагає забезпечити максимальну гнучкість та можливість повторного використання HOC. -## Конвенція: максимізація композиційності {#convention-maximizing-composability} +## Угода: максимізація композиційності {#convention-maximizing-composability} Не всі HOC виглядають однаково. Іноді вони приймають лише один аргумент — компонент, що буде обгорнений: @@ -262,10 +262,10 @@ const CommentWithRelay = Relay.createContainer(Comment, config); const ConnectedComment = connect(commentSelector, commentActions)(CommentList); ``` -*Що?!* Якщо розділити цей на частини, то легше буде побачити, що відбувається. +*Що?!* Якщо розділити це на частини, то легше буде побачити, що відбувається. ```js -// `connect` це фунція, що повертає іншу функцію +// `connect` це функція, що повертає іншу функцію const enhance = connect(commentListSelector, commentListActions); // Повернена функція є HOC, який поверне компонент підключенний до складу Redux const ConnectedComment = enhance(CommentList); @@ -293,7 +293,7 @@ const EnhancedComponent = enhance(WrappedComponent) Ви можете знайти допоміжну функцію `compose` у багатьох сторонніх бібліотеках, включаючи lodash (під назвою [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose) та [Ramda](https://ramdajs.com/docs/#compose). -## Конвенція: повертайте ім’я обгорнутого компонента для полегшення процессу {#convention-wrap-the-display-name-for-easy-debugging} +## Угода: повертайте ім’я обгорнутого компонента для полегшення процессу {#convention-wrap-the-display-name-for-easy-debugging} Створений HOC компонент-контейнер відображається в [React Develper Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат HOC. From 37da78183838bfa347fff9739ecea85a7c442e14 Mon Sep 17 00:00:00 2001 From: lazio Date: Tue, 17 Dec 2019 04:44:05 +0200 Subject: [PATCH 03/43] hoc translation updates --- content/docs/higher-order-components.md | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 11994ebf8..1ab02aa6e 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -12,9 +12,9 @@ permalink: docs/higher-order-components.html const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` -Якщо звичайний компонент перетворює props у UI, то компонент вищого порядку перетворює один компонент на інший. +Якщо звичайний компонент трасформує props у UI, то компонент вищого порядку трасформує один компонент у інший. -HOC поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. +HOC поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux, або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. У цьому розділі ми обговоримо чому компоненти вищого порядку корисні та як створювати власні. @@ -22,9 +22,9 @@ HOC поширені у таких сторонніх бібліотеках, я > **Примітка** > -> Раніше ми рекомендували міксині для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. +> Раніше ми рекомендували міксини для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. -Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак ви побачите, що вони не є відповідним рішенням для ряду проблем. +Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак ви побачите, що вони не є відповідним рішенням низки проблем. Наприклад, ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: @@ -106,7 +106,7 @@ class BlogPost extends React.Component { - Викликають `setState`, коли у джерелі даних відбуваються зміни. - При демонтуванні вони відписуються від `DataSource`. -Чи можете Ви уявити, що у великому додатку ця схема підписки буде виникати знову й знову? Нам потрібна абстракція, яка дозволить визначити цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречні компоненти вищого порядку. +Чи можете ви уявити, що у великому додатку ця схема підписки буде виникати знову і знову? Нам потрібна абстракція, яка дозволить описати цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречно використати компонент вищого порядку. Ми можемо написати функцію, що створює компоненти, як `CommentList` чи `BlogPost`, які підписуються на `DataSource`. В якості одного з аргументів функція буде приймати дочірній компонент, який отримає дані з підписки у якості власного prop. Назвемо цю функцію `withSubscription`: @@ -122,7 +122,7 @@ const BlogPostWithSubscription = withSubscription( ); ``` -Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` й props, та вилучає потрібні нам дані. +Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` та props, і вилучає потрібні нам дані. Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості prop з найактуальнішими даними, отриманими від `DataSource`: @@ -167,13 +167,13 @@ function withSubscription(WrappedComponent, selectData) { От і все! Обгорнутий компонент отримує всі props, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. -Оскільки `withSubscription` це звичайна функція, ви можете додати стільки аргументів, скільки забажаєте. Наприклад, ви вирішили зробити ім’я параметру `data` конфігуруємим, щоби додатково ізолювати HOC від обгорнутого компонента. Або Ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. +Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати HOC від обгорнутого компонента. Або Ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один HOC на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. ## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} -Втримайтеся від бажання змінити прототип компонента (або мутуваті його іншим чином) всередині HOC. +Втримайтеся від бажання змінити прототип компонента (чи мутуваті його) всередині HOC. ```js function logProps(InputComponent) { @@ -191,7 +191,7 @@ const EnhancedComponent = logProps(InputComponent); З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо Ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. -Мутуючи HOC є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими HOC. +Мутуючий HOC є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими HOC. Замість мутації, HOC мають реалізовувати композицію, обгортаючи переданий компонент у контейнер: @@ -212,7 +212,7 @@ function logProps(WrappedComponent) { Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама з собою. -Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси й внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. +Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. ## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} @@ -267,13 +267,13 @@ const ConnectedComment = connect(commentSelector, commentActions)(CommentList); ```js // `connect` це функція, що повертає іншу функцію const enhance = connect(commentListSelector, commentListActions); -// Повернена функція є HOC, який поверне компонент підключенний до складу Redux +// Повернена функція є HOC, який поверне компонент підключенний до Redux стору const ConnectedComment = enhance(CommentList); ``` Іншими словами, `connect` - це функція вищого порядку, яка повертає компонент вищого порядку! -Ця форма може здатися заплутаною або непотрібною, але вона має корисну властивість. Одноаргументні HOC, як і той, який повертається функцією `connect`, мають підпис `Component => Component`. Функції, з однаковим типом результату та єдиного аргументу, легко поєднуються у композицію. +Ця форма може здатися заплутаною або непотрібною, але вона має корисну властивість. Одноаргументні HOC, як і той, який повертається функцією `connect`, мають сигнатуру `Component => Component`. Функції, з однаковим типом результату та єдиного аргументу, легко поєднуються у композицію. ```js // Замість цього ... @@ -293,9 +293,9 @@ const EnhancedComponent = enhance(WrappedComponent) Ви можете знайти допоміжну функцію `compose` у багатьох сторонніх бібліотеках, включаючи lodash (під назвою [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose) та [Ramda](https://ramdajs.com/docs/#compose). -## Угода: повертайте ім’я обгорнутого компонента для полегшення процессу {#convention-wrap-the-display-name-for-easy-debugging} +## Угода: повертайте ім’я обгорнутого компонента для легшого дебагу {#convention-wrap-the-display-name-for-easy-debugging} -Створений HOC компонент-контейнер відображається в [React Develper Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат HOC. +Створений HOC компонент-контейнер відображається в [React Developer Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат HOC. Найпоширеніший прийом - обгортати відображуване ім’я загорнутого компонента. Отже, якщо ваш компонент вищого порядку названий `withSubscription`, а відображене ім’я загорнутого компонента - `CommentList`, визначте відображуване ім'я як `WithSubscription(CommentList)`: @@ -314,7 +314,7 @@ function getDisplayName(WrappedComponent) { ## Застереження {#caveats} -Якщо Ви лише починаєте використовувати React, то варто повідомити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. +Якщо Ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. ### Не використовуйте HOC у середині рендер-методів {#dont-use-hocs-inside-the-render-method} @@ -393,6 +393,6 @@ import MyComponent, { someFunction } from './MyComponent.js'; ### Refs не передаються {#refs-arent-passed-through} -Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, й тому інакше оброблюється React. Якщо Ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. +Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо Ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. Розв’язання цієї проблеми є використання API `React.forwardRef` (введений з React 16.3). [Дізнайтеся більше про це в розділі Переадресація рефів](/docs/forwarding-refs.html). From ca96649b832535b2853900242aaa038ec8994758 Mon Sep 17 00:00:00 2001 From: lazio Date: Tue, 17 Dec 2019 10:06:12 +0200 Subject: [PATCH 04/43] you with lowerace first letter --- content/docs/higher-order-components.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 1ab02aa6e..cd9d9bf3e 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -167,7 +167,7 @@ function withSubscription(WrappedComponent, selectData) { От і все! Обгорнутий компонент отримує всі props, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. -Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати HOC від обгорнутого компонента. Або Ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. +Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати HOC від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один HOC на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. @@ -189,7 +189,7 @@ function logProps(InputComponent) { const EnhancedComponent = logProps(InputComponent); ``` -З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо Ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. +З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. Мутуючий HOC є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими HOC. @@ -212,7 +212,7 @@ function logProps(WrappedComponent) { Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама з собою. -Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. +Можливо, ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. ## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} @@ -314,13 +314,13 @@ function getDisplayName(WrappedComponent) { ## Застереження {#caveats} -Якщо Ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. +Якщо ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. ### Не використовуйте HOC у середині рендер-методів {#dont-use-hocs-inside-the-render-method} Алгоритм порівняння React, що відомий як reconciliation (або узгодження), використовує перевірку на тотожність компонента, щоб визначити, чи слід оновити існуюче піддерево компонентів або слід знищити його та змонтувати нове. Якщо компонент, що був повернений рендер-методом, ідентичний (`===`) попередньому результату, React рекурсивно оновлює піддерева, порівнюючи його з новим. Якщо вони не тотожні, то попереднє піддерево буде повністю розмонтовано. -Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що Ви не можете застосувати HOC до компонента в рендер-методі іншого компонента: +Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що ви не можете застосувати HOC до компонента в рендер-методі іншого компонента: ```js render() { @@ -336,14 +336,14 @@ render() { Замість цього застосовуйте HOC за межами визначення компонента, щоб отриманий компонент був створений лише один раз. У цьому випадку React буде порівнювати один і той же компонент при повторному виклику рендер-метода. -У тих рідкісних випадках, коли вам потрібно динамічно застосовувати HOC, Ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. +У тих рідкісних випадках, коли вам потрібно динамічно застосовувати HOC, ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. ### Копіюйте статичні методи {#static-methods-must-be-copied-over} Іноді буває корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. -Якщо Ви застосовуєте HOC, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. +Якщо ви застосовуєте HOC, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. ```js // Визначте статичний метод @@ -366,7 +366,7 @@ function enhance(WrappedComponent) { } ``` -На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів Ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): +На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -393,6 +393,6 @@ import MyComponent, { someFunction } from './MyComponent.js'; ### Refs не передаються {#refs-arent-passed-through} -Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо Ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. +Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. Розв’язання цієї проблеми є використання API `React.forwardRef` (введений з React 16.3). [Дізнайтеся більше про це в розділі Переадресація рефів](/docs/forwarding-refs.html). From f73d16e6407248686763e6fe8282b68cce85407a Mon Sep 17 00:00:00 2001 From: lazio Date: Tue, 17 Dec 2019 10:29:44 +0200 Subject: [PATCH 05/43] replace you with capilat first letter --- content/docs/higher-order-components.md | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index cd9d9bf3e..954db9ce5 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -22,11 +22,11 @@ HOC поширені у таких сторонніх бібліотеках, я > **Примітка** > -> Раніше ми рекомендували міксини для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. +> Раніше ми рекомендували міксини для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як Ви можете переписати існуючі компоненти. -Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак ви побачите, що вони не є відповідним рішенням низки проблем. +Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак Ви побачите, що вони не є відповідним рішенням низки проблем. -Наприклад, ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: +Наприклад, Ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: ```js class CommentList extends React.Component { @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Пізніше, ви описуєте компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: +Пізніше, Ви описуєте компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: ```js class BlogPost extends React.Component { @@ -106,7 +106,7 @@ class BlogPost extends React.Component { - Викликають `setState`, коли у джерелі даних відбуваються зміни. - При демонтуванні вони відписуються від `DataSource`. -Чи можете ви уявити, що у великому додатку ця схема підписки буде виникати знову і знову? Нам потрібна абстракція, яка дозволить описати цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречно використати компонент вищого порядку. +Чи можете Ви уявити, що у великому додатку ця схема підписки буде виникати знову і знову? Нам потрібна абстракція, яка дозволить описати цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречно використати компонент вищого порядку. Ми можемо написати функцію, що створює компоненти, як `CommentList` чи `BlogPost`, які підписуються на `DataSource`. В якості одного з аргументів функція буде приймати дочірній компонент, який отримає дані з підписки у якості власного prop. Назвемо цю функцію `withSubscription`: @@ -167,9 +167,9 @@ function withSubscription(WrappedComponent, selectData) { От і все! Обгорнутий компонент отримує всі props, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. -Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати HOC від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. +Оскільки `withSubscription` це звичайна функція, Ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, Ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати HOC від обгорнутого компонента. Або Ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. -Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один HOC на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. +Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один HOC на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо Ви зміните бібліотеки для отримання даних. ## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} @@ -189,7 +189,7 @@ function logProps(InputComponent) { const EnhancedComponent = logProps(InputComponent); ``` -З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. +З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо Ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. Мутуючий HOC є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими HOC. @@ -212,7 +212,7 @@ function logProps(WrappedComponent) { Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама з собою. -Можливо, ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. +Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. ## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} @@ -314,13 +314,13 @@ function getDisplayName(WrappedComponent) { ## Застереження {#caveats} -Якщо ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. +Якщо Ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. ### Не використовуйте HOC у середині рендер-методів {#dont-use-hocs-inside-the-render-method} Алгоритм порівняння React, що відомий як reconciliation (або узгодження), використовує перевірку на тотожність компонента, щоб визначити, чи слід оновити існуюче піддерево компонентів або слід знищити його та змонтувати нове. Якщо компонент, що був повернений рендер-методом, ідентичний (`===`) попередньому результату, React рекурсивно оновлює піддерева, порівнюючи його з новим. Якщо вони не тотожні, то попереднє піддерево буде повністю розмонтовано. -Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що ви не можете застосувати HOC до компонента в рендер-методі іншого компонента: +Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що Ви не можете застосувати HOC до компонента в рендер-методі іншого компонента: ```js render() { @@ -336,14 +336,14 @@ render() { Замість цього застосовуйте HOC за межами визначення компонента, щоб отриманий компонент був створений лише один раз. У цьому випадку React буде порівнювати один і той же компонент при повторному виклику рендер-метода. -У тих рідкісних випадках, коли вам потрібно динамічно застосовувати HOC, ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. +У тих рідкісних випадках, коли вам потрібно динамічно застосовувати HOC, Ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. ### Копіюйте статичні методи {#static-methods-must-be-copied-over} Іноді буває корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. -Якщо ви застосовуєте HOC, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. +Якщо Ви застосовуєте HOC, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. ```js // Визначте статичний метод @@ -366,7 +366,7 @@ function enhance(WrappedComponent) { } ``` -На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): +На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів Ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -393,6 +393,6 @@ import MyComponent, { someFunction } from './MyComponent.js'; ### Refs не передаються {#refs-arent-passed-through} -Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. +Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо Ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. Розв’язання цієї проблеми є використання API `React.forwardRef` (введений з React 16.3). [Дізнайтеся більше про це в розділі Переадресація рефів](/docs/forwarding-refs.html). From ea41b4ff1b6f86390f228135cfafc9c180a0762d Mon Sep 17 00:00:00 2001 From: lazio Date: Tue, 17 Dec 2019 13:47:26 +0200 Subject: [PATCH 06/43] typo --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 954db9ce5..b5c5a4bb8 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -173,7 +173,7 @@ function withSubscription(WrappedComponent, selectData) { ## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} -Втримайтеся від бажання змінити прототип компонента (чи мутуваті його) всередині HOC. +Втримайтеся від бажання змінити прототип компонента (чи мутувати його) всередині HOC. ```js function logProps(InputComponent) { From 00937c10e71ea8210f2a8ad486d3ddf5da466a33 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab Date: Wed, 18 Dec 2019 17:21:05 +0200 Subject: [PATCH 07/43] Checked all. --- gatsby-config.js | 6 ++++-- src/components/CodeEditor/CodeEditor.js | 5 +++-- src/components/ErrorDecoder/ErrorDecoder.js | 4 ++-- src/pages/index.js | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/gatsby-config.js b/gatsby-config.js index 746bb781a..5a781d5af 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -8,10 +8,12 @@ module.exports = { siteMetadata: { - title: 'React – JavaScript-бібліотека для створення користувацьких інтерфейсів', + title: + 'React – JavaScript-бібліотека для створення користувацьких інтерфейсів', siteUrl: 'https://uk.reactjs.org', rssFeedTitle: 'React', - rssFeedDescription: 'JavaScript-бібліотека для створення користувацьких інтерфейсів', + rssFeedDescription: + 'JavaScript-бібліотека для створення користувацьких інтерфейсів', }, mapping: { 'MarkdownRemark.frontmatter.author': 'AuthorYaml', diff --git a/src/components/CodeEditor/CodeEditor.js b/src/components/CodeEditor/CodeEditor.js index 3f8e1fadf..2ba88728b 100644 --- a/src/components/CodeEditor/CodeEditor.js +++ b/src/components/CodeEditor/CodeEditor.js @@ -65,8 +65,9 @@ class CodeEditor extends Component { Не вдалося завантажити Babel.

- Це може бути пов'язано з блокувальником реклами. Якщо ви використовуєте один з них, - додайте адресу reactjs.org до білого списку для того, щоб приклади коду запрацювали. + Це може бути пов'язано з блокувальником реклами. Якщо ви + використовуєте один з них, додайте адресу reactjs.org до білого списку + для того, щоб приклади коду запрацювали. ); } else if (error != null) { diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index 32e6146ac..2f0627126 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -69,8 +69,8 @@ function ErrorResult(props: {|code: ?string, msg: string|}) { if (!code) { return (

- Коли трапляється помилка, ви отримаєте посилання на цю сторінку, - де ви побачите повний текст конкретної помилки. + Коли трапляється помилка, ви отримаєте посилання на цю сторінку, де ви + побачите повний текст конкретної помилки.

); } diff --git a/src/pages/index.js b/src/pages/index.js index e9f852ace..fe3baa03a 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -133,7 +133,8 @@ class Home extends Component { fontSize: 30, }, }}> - JavaScript-бібліотека для створення користувацьких інтерфейсів + JavaScript-бібліотека для створення користувацьких + інтерфейсів

Date: Fri, 27 Dec 2019 11:54:36 +0200 Subject: [PATCH 08/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index b5c5a4bb8..bebccc7ba 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -12,7 +12,7 @@ permalink: docs/higher-order-components.html const EnhancedComponent = higherOrderComponent(WrappedComponent); ``` -Якщо звичайний компонент трасформує props у UI, то компонент вищого порядку трасформує один компонент у інший. +Якщо звичайний компонент трасформує пропси у UI, то компонент вищого порядку трасформує один компонент у інший. HOC поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux, або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. From 52c3dc9d816d05fbdc90a42a22f524a7af670712 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:54:45 +0200 Subject: [PATCH 09/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index bebccc7ba..34e288a70 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -4,7 +4,7 @@ title: Компоненти вищого порядку permalink: docs/higher-order-components.html --- -Компонент вищого порядку (Higher-Order Component, HOC) — це просунута технологія для повторного використання логіки компоненту. Сам по собі HOC не є частиною React API, але через композиційну природу компонентів він є розповсюдженним патерном проектування. +Компонент вищого порядку (КВП) — це просунута технологія для повторного використання логіки компоненту. Сам по собі КВП не є частиною React API, але через композиційну природу компонентів він є розповсюдженним патерном проектування. Тобто, **компонент вищого порядку — це функція, яка приймає компонент та повертає новий компонент.** From 4833a91dc41907659517b6b5678d3ab59f885bd5 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:54:51 +0200 Subject: [PATCH 10/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 34e288a70..28d70e14d 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -16,7 +16,7 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); HOC поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux, або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. -У цьому розділі ми обговоримо чому компоненти вищого порядку корисні та як створювати власні. +У цьому розділі ми обговоримо чому компоненти вищого порядку корисні та як створювати їх власноруч. ## Використання HOC для перехресної функціональності {#use-hocs-for-cross-cutting-concerns} From 2f9bab3d072aa2a84e0dcef328a697b5d353c697 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:54:56 +0200 Subject: [PATCH 11/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 28d70e14d..03784bb37 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -14,7 +14,7 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); Якщо звичайний компонент трасформує пропси у UI, то компонент вищого порядку трасформує один компонент у інший. -HOC поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux, або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. +КВП поширені у таких сторонніх бібліотеках, як [`connect`](https://github.com/reduxjs/react-redux/blob/master/docs/api/connect.md#connect) у Redux, або [`createFragmentContainer`](http://facebook.github.io/relay/docs/en/fragment-container.html) у Relay. У цьому розділі ми обговоримо чому компоненти вищого порядку корисні та як створювати їх власноруч. From ed26b5d8c83351a60a0058ab17760361d96a93a8 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:55:06 +0200 Subject: [PATCH 12/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 03784bb37..256e99b25 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -18,7 +18,7 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); У цьому розділі ми обговоримо чому компоненти вищого порядку корисні та як створювати їх власноруч. -## Використання HOC для перехресної функціональності {#use-hocs-for-cross-cutting-concerns} +## Використання КВП для перехресної функціональності {#use-hocs-for-cross-cutting-concerns} > **Примітка** > From f511dcc12b35761d07c1c7b017a8943365526dca Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:55:12 +0200 Subject: [PATCH 13/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 256e99b25..591fe95b2 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -22,7 +22,7 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); > **Примітка** > -> Раніше ми рекомендували міксини для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як Ви можете переписати існуючі компоненти. +> Раніше ми рекомендували міксини для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак Ви побачите, що вони не є відповідним рішенням низки проблем. From 3a04cb4cb536137c6e637d5d57ae6c94680d6cb6 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:55:19 +0200 Subject: [PATCH 14/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 591fe95b2..ee63a770c 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Пізніше, Ви описуєте компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: +Пізніше, ви описуєте компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: ```js class BlogPost extends React.Component { From e41cb93857e39daf2291d6fddeeb61a2b6d35065 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:55:33 +0200 Subject: [PATCH 15/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index ee63a770c..915423b16 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -26,7 +26,7 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак Ви побачите, що вони не є відповідним рішенням низки проблем. -Наприклад, Ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: +Наприклад, ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: ```js class CommentList extends React.Component { From 15ade19b5522531332a8a65fbe613323de1a09f8 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Fri, 27 Dec 2019 11:55:39 +0200 Subject: [PATCH 16/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 915423b16..ec43ce7e5 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -24,7 +24,7 @@ const EnhancedComponent = higherOrderComponent(WrappedComponent); > > Раніше ми рекомендували міксини для реалізації перехресної функціональності. Але з часом ми з’ясували, що від них більше клопоту, ніж користі. [Дізнайтеся більше](/blog/2016/07/13/mixins-considered-harmful.html) про те, чому ми відмовилися від міксинів та як ви можете переписати існуючі компоненти. -Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак Ви побачите, що вони не є відповідним рішенням низки проблем. +Зазвичай компоненти є основною одиницею повторного використання коду у React. Однак ви побачите, що вони не є відповідним рішенням низки проблем. Наприклад, ви маєте компонент `CommentList`, який підписується на зовнішнє джерело даних, щоб відобразити список коментарів: From 825838b05fa858c19371f5cf826784eec81002a0 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab Date: Fri, 27 Dec 2019 12:12:05 +0200 Subject: [PATCH 17/43] Fixed translation according to instructions. --- content/docs/higher-order-components.md | 64 ++++++++++++------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index ec43ce7e5..abbfb52d2 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -106,7 +106,7 @@ class BlogPost extends React.Component { - Викликають `setState`, коли у джерелі даних відбуваються зміни. - При демонтуванні вони відписуються від `DataSource`. -Чи можете Ви уявити, що у великому додатку ця схема підписки буде виникати знову і знову? Нам потрібна абстракція, яка дозволить описати цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречно використати компонент вищого порядку. +Чи можете ви уявити, що у великому додатку ця схема підписки буде виникати знову і знову? Нам потрібна абстракція, яка дозволить описати цю логіку в одному місці та звертатися до неї у багатьох компонентах. Саме тут доречно використати компонент вищого порядку. Ми можемо написати функцію, що створює компоненти, як `CommentList` чи `BlogPost`, які підписуються на `DataSource`. В якості одного з аргументів функція буде приймати дочірній компонент, який отримає дані з підписки у якості власного prop. Назвемо цю функцію `withSubscription`: @@ -163,17 +163,17 @@ function withSubscription(WrappedComponent, selectData) { } ``` -Зверніть увагу на те, що HOC не модифікує отриманий компонент та не наслідує його поведінку. Швидше, HOC створює *композицію*, *обгортаючи* оригінальний компонент у контейнер. HOC є чистою функцією без побічних ефектів. +Зверніть увагу на те, що КВП не модифікує отриманий компонент та не наслідує його поведінку. Швидше, КВП створює *композицію*, *обгортаючи* оригінальний компонент у контейнер. КВП є чистою функцією без побічних ефектів. От і все! Обгорнутий компонент отримує всі props, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. -Оскільки `withSubscription` це звичайна функція, Ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, Ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати HOC від обгорнутого компонента. Або Ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що HOC має повний контроль над тим, як компонент буде визначений. +Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати КВП від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що КВП має повний контроль над тим, як компонент буде визначений. -Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один HOC на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо Ви зміните бібліотеки для отримання даних. +Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один КВП на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. ## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} -Втримайтеся від бажання змінити прототип компонента (чи мутувати його) всередині HOC. +Втримайтеся від бажання змінити прототип компонента (чи мутувати його) всередині КВП. ```js function logProps(InputComponent) { @@ -189,11 +189,11 @@ function logProps(InputComponent) { const EnhancedComponent = logProps(InputComponent); ``` -З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо Ви застосуєте інший HOC до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого HOC буде перезаписана! Цей HOC також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. +З цим пов'язано кілька проблем. Одна полягає у тому, що `InputComponent` не може бути використаний знову окремо від `EnhancedComponent`. Більш важливо, якщо ви застосуєте інший КВП до `EnhancedComponent`, який, наприклад, у свою чергу мутує `componentWillReceiveProps`, функціональність першого КВП буде перезаписана! Цей КВП також не буде працювати з функціональними компонентами, які не мають методів життєвого циклу. -Мутуючий HOC є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими HOC. +Мутуючий КВП є крихкою абстракцією — споживач повинен знати, як вони реалізуються, щоб уникнути конфліктів з іншими КВП. -Замість мутації, HOC мають реалізовувати композицію, обгортаючи переданий компонент у контейнер: +Замість мутації, КВП мають реалізовувати композицію, обгортаючи переданий компонент у контейнер: ```js function logProps(WrappedComponent) { @@ -210,19 +210,19 @@ function logProps(WrappedComponent) { } ``` -Цей HOC має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим HOC, або навіть сама з собою. +Цей КВП має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим КВП, або навіть сама з собою. -Можливо, Ви вже помітили схожість між HOC та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. HOC використовують контейнери, як частину власної реалізації. Ви можете вважати HOC параметризованим визначенням компонента-контейнера. +Можливо, ви вже помітили схожість між КВП та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. КВП використовують контейнери, як частину власної реалізації. Ви можете вважати КВП параметризованим визначенням компонента-контейнера. ## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} -HOC додає компоненту функціональність. Він не повинен змінювати його початкове призначення. Очікується, що повернений HOC компонент буде мати інтерфейс аналогічний обгорнутому. +КВП додає компоненту функціональність. Він не повинен змінювати його початкове призначення. Очікується, що повернений КВП компонент буде мати інтерфейс аналогічний обгорнутому. -HOC повинні передавати ті props, що не пов'язані з їх функціональністю, у незмінному стані. Більшість компонентів вищого порядку мають рендер-метод, схожий на цей: +КВП повинні передавати ті props, що не пов'язані з їх функціональністю, у незмінному стані. Більшість компонентів вищого порядку мають рендер-метод, схожий на цей: ```js render() { - // Відфільтруйте зайві props, що характерні для HOC та не мають потрапити до компонента + // Відфільтруйте зайві props, що характерні для КВП та не мають потрапити до компонента const { extraProp, ...passThroughProps } = this.props; // Створіть ін’єкцію для обгорнутого компонента. @@ -239,23 +239,23 @@ render() { } ``` -Ця угода допомагає забезпечити максимальну гнучкість та можливість повторного використання HOC. +Ця угода допомагає забезпечити максимальну гнучкість та можливість повторного використання КВП. ## Угода: максимізація композиційності {#convention-maximizing-composability} -Не всі HOC виглядають однаково. Іноді вони приймають лише один аргумент — компонент, що буде обгорнений: +Не всі КВП виглядають однаково. Іноді вони приймають лише один аргумент — компонент, що буде обгорнений: ```js const NavbarWithRouter = withRouter(Navbar); ``` -Зазвичай HOC приймає додаткові аргументи. У цьому прикладі з Relay об’єкт конфігурації використовується для визначення залежностей даних компонента: +Зазвичай КВП приймає додаткові аргументи. У цьому прикладі з Relay об’єкт конфігурації використовується для визначення залежностей даних компонента: ```js const CommentWithRelay = Relay.createContainer(Comment, config); ``` -Найбільш поширений спосіб виклику HOC виглядає так: +Найбільш поширений спосіб виклику КВП виглядає так: ```js // Функція `connect` у React та Redux @@ -267,35 +267,35 @@ const ConnectedComment = connect(commentSelector, commentActions)(CommentList); ```js // `connect` це функція, що повертає іншу функцію const enhance = connect(commentListSelector, commentListActions); -// Повернена функція є HOC, який поверне компонент підключенний до Redux стору +// Повернена функція є КВП, який поверне компонент підключенний до Redux стору const ConnectedComment = enhance(CommentList); ``` Іншими словами, `connect` - це функція вищого порядку, яка повертає компонент вищого порядку! -Ця форма може здатися заплутаною або непотрібною, але вона має корисну властивість. Одноаргументні HOC, як і той, який повертається функцією `connect`, мають сигнатуру `Component => Component`. Функції, з однаковим типом результату та єдиного аргументу, легко поєднуються у композицію. +Ця форма може здатися заплутаною або непотрібною, але вона має корисну властивість. Одноаргументні КВП, як і той, який повертається функцією `connect`, мають сигнатуру `Component => Component`. Функції, з однаковим типом результату та єдиного аргументу, легко поєднуються у композицію. ```js // Замість цього ... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) -// ... Ви можете використати композиційну функцію +// ... ви можете використати композиційну функцію // compose(f, g, h) теж саме, що (...args) => f(g(h(...args))) const enhance = compose( - // Обидва параметра є HOC та приймають лише один аргумент + // Обидва параметра є КВП та приймають лише один аргумент withRouter, connect(commentSelector) ) const EnhancedComponent = enhance(WrappedComponent) ``` -(Саме ця властивість дозволяє використовувати `connect` та інші поширюючи функціональність HOC у якості експериментальних JavaScript декораторів.) +(Саме ця властивість дозволяє використовувати `connect` та інші поширюючи функціональність КВП у якості експериментальних JavaScript декораторів.) Ви можете знайти допоміжну функцію `compose` у багатьох сторонніх бібліотеках, включаючи lodash (під назвою [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose) та [Ramda](https://ramdajs.com/docs/#compose). ## Угода: повертайте ім’я обгорнутого компонента для легшого дебагу {#convention-wrap-the-display-name-for-easy-debugging} -Створений HOC компонент-контейнер відображається в [React Developer Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат HOC. +Створений КВП компонент-контейнер відображається в [React Developer Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат КВП. Найпоширеніший прийом - обгортати відображуване ім’я загорнутого компонента. Отже, якщо ваш компонент вищого порядку названий `withSubscription`, а відображене ім’я загорнутого компонента - `CommentList`, визначте відображуване ім'я як `WithSubscription(CommentList)`: @@ -314,13 +314,13 @@ function getDisplayName(WrappedComponent) { ## Застереження {#caveats} -Якщо Ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. +Якщо ви лише починаєте використовувати React, то варто зазначити, що компоненти вищого порядку можуть стати причиною неочевидних проблем. -### Не використовуйте HOC у середині рендер-методів {#dont-use-hocs-inside-the-render-method} +### Не використовуйте КВП у середині рендер-методів {#dont-use-hocs-inside-the-render-method} Алгоритм порівняння React, що відомий як reconciliation (або узгодження), використовує перевірку на тотожність компонента, щоб визначити, чи слід оновити існуюче піддерево компонентів або слід знищити його та змонтувати нове. Якщо компонент, що був повернений рендер-методом, ідентичний (`===`) попередньому результату, React рекурсивно оновлює піддерева, порівнюючи його з новим. Якщо вони не тотожні, то попереднє піддерево буде повністю розмонтовано. -Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що Ви не можете застосувати HOC до компонента в рендер-методі іншого компонента: +Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що ви не можете застосувати КВП до компонента в рендер-методі іншого компонента: ```js render() { @@ -334,21 +334,21 @@ render() { Проблема тут полягає не лише в продуктивності — повторне перерахування компонента втрачає стан цього компонента та всіх його потомків. -Замість цього застосовуйте HOC за межами визначення компонента, щоб отриманий компонент був створений лише один раз. У цьому випадку React буде порівнювати один і той же компонент при повторному виклику рендер-метода. +Замість цього застосовуйте КВП за межами визначення компонента, щоб отриманий компонент був створений лише один раз. У цьому випадку React буде порівнювати один і той же компонент при повторному виклику рендер-метода. -У тих рідкісних випадках, коли вам потрібно динамічно застосовувати HOC, Ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. +У тих рідкісних випадках, коли вам потрібно динамічно застосовувати КВП, ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. ### Копіюйте статичні методи {#static-methods-must-be-copied-over} Іноді буває корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. -Якщо Ви застосовуєте HOC, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. +Якщо ви застосовуєте КВП, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. ```js // Визначте статичний метод WrappedComponent.staticMethod = function() {/*...*/} -// Тепер застосуйте HOC +// Тепер застосуйте КВП const EnhancedComponent = enhance(WrappedComponent); // EnhancedComponent не має статичного методу @@ -366,7 +366,7 @@ function enhance(WrappedComponent) { } ``` -На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів Ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): +На жаль для цього необхідно точно знати, які методи потрібно скопіювати. Для автоматичного копіювання всіх статичних методів ви можете використати [`hoist-non-react-statics`](https://github.com/mridgway/hoist-non-react-statics): ```js import hoistNonReactStatic from 'hoist-non-react-statics'; @@ -393,6 +393,6 @@ import MyComponent, { someFunction } from './MyComponent.js'; ### Refs не передаються {#refs-arent-passed-through} -Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо Ви додасте `ref` до компонента, що був повернений HOC, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. +Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо ви додасте `ref` до компонента, що був повернений КВП, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. Розв’язання цієї проблеми є використання API `React.forwardRef` (введений з React 16.3). [Дізнайтеся більше про це в розділі Переадресація рефів](/docs/forwarding-refs.html). From 973a89602960088167fb073e62783859f68025b5 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab Date: Wed, 15 Jan 2020 17:18:11 +0200 Subject: [PATCH 18/43] Fix: text formatting has been reverted. --- gatsby-config.js | 6 ++---- src/components/CodeEditor/CodeEditor.js | 5 ++--- src/components/ErrorDecoder/ErrorDecoder.js | 4 ++-- src/pages/index.js | 5 ++--- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/gatsby-config.js b/gatsby-config.js index 5a781d5af..746bb781a 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -8,12 +8,10 @@ module.exports = { siteMetadata: { - title: - 'React – JavaScript-бібліотека для створення користувацьких інтерфейсів', + title: 'React – JavaScript-бібліотека для створення користувацьких інтерфейсів', siteUrl: 'https://uk.reactjs.org', rssFeedTitle: 'React', - rssFeedDescription: - 'JavaScript-бібліотека для створення користувацьких інтерфейсів', + rssFeedDescription: 'JavaScript-бібліотека для створення користувацьких інтерфейсів', }, mapping: { 'MarkdownRemark.frontmatter.author': 'AuthorYaml', diff --git a/src/components/CodeEditor/CodeEditor.js b/src/components/CodeEditor/CodeEditor.js index 2ba88728b..3f8e1fadf 100644 --- a/src/components/CodeEditor/CodeEditor.js +++ b/src/components/CodeEditor/CodeEditor.js @@ -65,9 +65,8 @@ class CodeEditor extends Component { Не вдалося завантажити Babel.

- Це може бути пов'язано з блокувальником реклами. Якщо ви - використовуєте один з них, додайте адресу reactjs.org до білого списку - для того, щоб приклади коду запрацювали. + Це може бути пов'язано з блокувальником реклами. Якщо ви використовуєте один з них, + додайте адресу reactjs.org до білого списку для того, щоб приклади коду запрацювали. ); } else if (error != null) { diff --git a/src/components/ErrorDecoder/ErrorDecoder.js b/src/components/ErrorDecoder/ErrorDecoder.js index 2f0627126..32e6146ac 100644 --- a/src/components/ErrorDecoder/ErrorDecoder.js +++ b/src/components/ErrorDecoder/ErrorDecoder.js @@ -69,8 +69,8 @@ function ErrorResult(props: {|code: ?string, msg: string|}) { if (!code) { return (

- Коли трапляється помилка, ви отримаєте посилання на цю сторінку, де ви - побачите повний текст конкретної помилки. + Коли трапляється помилка, ви отримаєте посилання на цю сторінку, + де ви побачите повний текст конкретної помилки.

); } diff --git a/src/pages/index.js b/src/pages/index.js index fe3baa03a..e9f852ace 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -133,8 +133,7 @@ class Home extends Component { fontSize: 30, }, }}> - JavaScript-бібліотека для створення користувацьких - інтерфейсів + JavaScript-бібліотека для створення користувацьких інтерфейсів

Date: Mon, 20 Jan 2020 09:02:03 +0200 Subject: [PATCH 19/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index abbfb52d2..0a6721259 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -68,7 +68,7 @@ class CommentList extends React.Component { } ``` -Пізніше, ви описуєте компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: +Пізніше, ви створите компонент `BlogPost` для підписки на одну публікацію блогу, який реалізується за схожою логікою: ```js class BlogPost extends React.Component { From fd032a1fac68ca00f12a745f9411a91d65611510 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:02:14 +0200 Subject: [PATCH 20/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 0a6721259..5516e8ba6 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -122,7 +122,7 @@ const BlogPostWithSubscription = withSubscription( ); ``` -Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` та props, і вилучає потрібні нам дані. +Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` та пропси, і вилучає потрібні нам дані. Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості prop з найактуальнішими даними, отриманими від `DataSource`: From d8807814d48d42e5765a4fd2054d9a8fa9504b41 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:02:32 +0200 Subject: [PATCH 21/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 5516e8ba6..d7804c73d 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -156,7 +156,7 @@ function withSubscription(WrappedComponent, selectData) { render() { // ... та відображується обгорнутий компонент зі свіжими даними! - // Зверніть увагу, що ми передаємо усі props + // Зверніть увагу, що ми передаємо усі пропси return ; } }; From a13cd87466b9f7e5d5eb74849c349a9222fb5525 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:02:40 +0200 Subject: [PATCH 22/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index d7804c73d..9e97c71af 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -341,7 +341,7 @@ render() { ### Копіюйте статичні методи {#static-methods-must-be-copied-over} -Іноді буває корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. +Іноді корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. Якщо ви застосовуєте КВП, то обгортаєте оригінальний компонент контейнером. Це означає, що новий компонент не матиме статичних методів оригінального компонента. From c3ae4e1fa6860b024be8a03d668ec0d9aa321166 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:02:48 +0200 Subject: [PATCH 23/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 9e97c71af..15b22a5ec 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -338,7 +338,6 @@ render() { У тих рідкісних випадках, коли вам потрібно динамічно застосовувати КВП, ви можете зробити це в методах життєвого циклу компонента або в його конструкторі. - ### Копіюйте статичні методи {#static-methods-must-be-copied-over} Іноді корисно визначити статичні методи компонента. Наприклад, статичний метод `getFragment` у бібліотеці Relay дає можливість визначити композицію з фрагментів даних GraphQL. From 0154208df4012ed237244ffb5cd3fd9b4ea03d6e Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:03:02 +0200 Subject: [PATCH 24/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 15b22a5ec..80851cd2f 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -100,7 +100,7 @@ class BlogPost extends React.Component { } ``` -`CommentList` та `BlogPost` не є ідентичними — вони викликають різні методи `DataSource` та вони відображають різний UI. Однак значна частина їх реалізації збігається: +`CommentList` та `BlogPost` не є ідентичними — вони викликають різні методи `DataSource` та відображають різний інтерфейс. Однак значна частина їх реалізації збігається: - Після монтування вони підписуються на зміни у `DataSource`. - Викликають `setState`, коли у джерелі даних відбуваються зміни. From 94a0e5de56a8a23b96f5a0663c99cce061d1c54a Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:03:10 +0200 Subject: [PATCH 25/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 80851cd2f..32edb233a 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -124,7 +124,7 @@ const BlogPostWithSubscription = withSubscription( Перший параметр це обгорнутий компонент, а другий — функція, що отримує `DataSource` та пропси, і вилучає потрібні нам дані. -Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості prop з найактуальнішими даними, отриманими від `DataSource`: +Коли `CommentListWithSubscription` і `BlogPostWithSubscription` відображаються, у `CommentList` і `BlogPost` буде переданий параметр `data` у якості пропа з актуальними даними, отриманими від `DataSource`: ```js // Ця функція отримує компонент ... From 8e833a3e23d3ebe0739554bda51705ea8b4dc7b5 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:03:20 +0200 Subject: [PATCH 26/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 32edb233a..2677d738c 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -327,7 +327,7 @@ render() { // Під час кожного виклику рендер-методу створюється новий екземпляр EnhancedComponent // EnhancedComponent1 !== EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); - // Це призводить до того, що все піддерево щоразу перераховується! + // Це призводить до того, що все піддерево щоразу монтується/демонтується! return ; } ``` From 3a33c6724a39069b74b04ff8cb02919b191ce67a Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:03:31 +0200 Subject: [PATCH 27/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 2677d738c..f5d9b43d1 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -165,7 +165,7 @@ function withSubscription(WrappedComponent, selectData) { Зверніть увагу на те, що КВП не модифікує отриманий компонент та не наслідує його поведінку. Швидше, КВП створює *композицію*, *обгортаючи* оригінальний компонент у контейнер. КВП є чистою функцією без побічних ефектів. -От і все! Обгорнутий компонент отримує всі props, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. +От і все! Обгорнутий компонент отримує всі пропси, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати КВП від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що КВП має повний контроль над тим, як компонент буде визначений. From 44742a2682f2594bc35b8317e71b72f73962fb30 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:03:44 +0200 Subject: [PATCH 28/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index f5d9b43d1..fa4d5122f 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -167,7 +167,7 @@ function withSubscription(WrappedComponent, selectData) { От і все! Обгорнутий компонент отримує всі пропси, що були передані до контейнера, разом з новим prop — `data`, який він використовує для відображення UI. Для компонента вищого порядку не має значення, як саме дані будуть використані, а для обгорнутого компонента не має значення, звідки вони з'явились. -Оскільки `withSubscription` це звичайна функція, ви вільні додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати КВП від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що КВП має повний контроль над тим, як компонент буде визначений. +Оскільки `withSubscription` це звичайна функція, ви можете додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати КВП від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що КВП має повний контроль над тим, як компонент буде визначений. Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один КВП на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. From 1f6d503f6e29bc7927fa246828d59cb5893632a1 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:04:00 +0200 Subject: [PATCH 29/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index fa4d5122f..a756807e9 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -390,7 +390,7 @@ export { someFunction }; import MyComponent, { someFunction } from './MyComponent.js'; ``` -### Refs не передаються {#refs-arent-passed-through} +### Рефи не передаються {#refs-arent-passed-through} Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо ви додасте `ref` до компонента, що був повернений КВП, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. From 4b72cf199ca0061df445e76fa6502d72567a38d3 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:04:08 +0200 Subject: [PATCH 30/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index a756807e9..186670840 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -392,6 +392,6 @@ import MyComponent, { someFunction } from './MyComponent.js'; ### Рефи не передаються {#refs-arent-passed-through} -Попри те, що попередня конвенція наполягає на тому, щоб передавати всі props до обгорнутого компонента, це не стосується refs. Річ у тому, що `ref` насправді не є prop, як, наприклад, `key`, тому інакше оброблюється React. Якщо ви додасте `ref` до компонента, що був повернений КВП, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. +Попри те, що попередня конвенція наполягає на тому, щоб передавати всі пропси до обгорнутого компонента, це не стосується рефів. Річ у тому, що `ref` насправді не є пропом, як, наприклад, `key`, а тому інакше оброблюється React. Якщо ви додасте `ref` до компонента, що був повернений КВП, він буде вказувати на екземпляр зовнішнього контейнера, а не на обгорнутий компонент. Розв’язання цієї проблеми є використання API `React.forwardRef` (введений з React 16.3). [Дізнайтеся більше про це в розділі Переадресація рефів](/docs/forwarding-refs.html). From 602860ef31fda4303aac8db2cf9f70d496a0922b Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:04:25 +0200 Subject: [PATCH 31/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 186670840..7b40d547c 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -169,7 +169,7 @@ function withSubscription(WrappedComponent, selectData) { Оскільки `withSubscription` це звичайна функція, ви можете додати стільки аргументів, скільки забажаєте. Наприклад, ви можете зробити ім’я параметру `data` конфігуруємим, щоб додатково ізолювати КВП від обгорнутого компонента. Або ви можете прийняти аргумент, що налаштує `shouldComponentUpdate` чи джерело даних. Це все можливо тому, що КВП має повний контроль над тим, як компонент буде визначений. -Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою props. Це дозволяє легко замінити один КВП на інший, якщо вони забезпечують однакові props для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. +Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою пропсів. Це дозволяє легко замінити один КВП на інший, якщо вони забезпечують однакові пропси для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. ## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} From f9250f66bee694863cefcc72a3a5d5e59a2c9c5e Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:04:39 +0200 Subject: [PATCH 32/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 7b40d547c..2ddd3daef 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -171,7 +171,7 @@ function withSubscription(WrappedComponent, selectData) { Як і між звичайними компонентами, взаємодія між `withSubscription` і обгорнутим компонентом здійснюється лише за допомогою пропсів. Це дозволяє легко замінити один КВП на інший, якщо вони забезпечують однакові пропси для обгорнутого компонента. Це може бути корисним, наприклад, якщо ви зміните бібліотеки для отримання даних. -## Не мутуйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} +## Не змінюйте обгорнутий компонент. Використовуйте композицію. {#dont-mutate-the-original-component-use-composition} Втримайтеся від бажання змінити прототип компонента (чи мутувати його) всередині КВП. From f2f47baf8b8566d3cc5717a7488156ae46585a33 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:04:52 +0200 Subject: [PATCH 33/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 2ddd3daef..6064c5c12 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -185,7 +185,7 @@ function logProps(InputComponent) { return InputComponent; } -// EnhancedComponent буде щоразу друкувати в консоль, коли отримає новий prop +// EnhancedComponent буде щоразу друкувати в консоль, коли отримає новий проп const EnhancedComponent = logProps(InputComponent); ``` From 5143fbf8b010e62f7ff066c01a32d60c8d26f762 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:05:03 +0200 Subject: [PATCH 34/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 6064c5c12..a455b232f 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -212,7 +212,7 @@ function logProps(WrappedComponent) { Цей КВП має таку ж функціональність, як і мутована версія, уникаючи при цьому можливих проблем. Він однаково добре працює з класовими та функціональними компонентами. А тому, що це чиста функція, вона може бути поєднана з іншим КВП, або навіть сама з собою. -Можливо, ви вже помітили схожість між КВП та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають props у компоненти, що у свою чергу відповідають за відображення UI. КВП використовують контейнери, як частину власної реалізації. Ви можете вважати КВП параметризованим визначенням компонента-контейнера. +Можливо, ви вже помітили схожість між КВП та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають пропси у компоненти, що у свою чергу відповідають за відображення UI. КВП використовують контейнери, як частину власної реалізації. Ви можете вважати КВП параметризованим визначенням компонента-контейнера. ## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} From 8c26599b431198b86b43829a7911f21c225bfa4a Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:05:16 +0200 Subject: [PATCH 35/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index a455b232f..3a2c83ae8 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -214,7 +214,7 @@ function logProps(WrappedComponent) { Можливо, ви вже помітили схожість між КВП та патерном, що називається компонент-контейнер. Нагадаємо, що **компонент-контейнер** є частиною політики відокремлення відповідальності між високорівневими та низькорівневими задачами. Контейнери керують такими речами, як підписка на зовнішні ресурси та внутрішній стан, та передають пропси у компоненти, що у свою чергу відповідають за відображення UI. КВП використовують контейнери, як частину власної реалізації. Ви можете вважати КВП параметризованим визначенням компонента-контейнера. -## Угода: передавайте сторонні props обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} +## Конвенція: передавайте сторонні пропси обгорненому компоненту {#convention-pass-unrelated-props-through-to-the-wrapped-component} КВП додає компоненту функціональність. Він не повинен змінювати його початкове призначення. Очікується, що повернений КВП компонент буде мати інтерфейс аналогічний обгорнутому. From 985615894bea22ba6076e62db1050d6f8ef7f330 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:05:30 +0200 Subject: [PATCH 36/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 3a2c83ae8..fb56d0c8d 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -218,7 +218,7 @@ function logProps(WrappedComponent) { КВП додає компоненту функціональність. Він не повинен змінювати його початкове призначення. Очікується, що повернений КВП компонент буде мати інтерфейс аналогічний обгорнутому. -КВП повинні передавати ті props, що не пов'язані з їх функціональністю, у незмінному стані. Більшість компонентів вищого порядку мають рендер-метод, схожий на цей: +КВП повинні передавати ті пропси, що не пов'язані з їх функціональністю, у незмінному стані. Більшість компонентів вищого порядку мають рендер-метод, схожий на цей: ```js render() { From 216b646acbdcd6b66ad9087d82f4e7a0d82b76b5 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:05:44 +0200 Subject: [PATCH 37/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index fb56d0c8d..e7ac273cb 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -222,7 +222,8 @@ function logProps(WrappedComponent) { ```js render() { - // Відфільтруйте зайві props, що характерні для КВП та не мають потрапити до компонента + // Відфільтруйте зайві пропси, що характерні для КВП та не мають + // потрапити до компонента const { extraProp, ...passThroughProps } = this.props; // Створіть ін’єкцію для обгорнутого компонента. From 83d7edd975ec1fd6bda481a3ac60929c0be6938e Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:05:57 +0200 Subject: [PATCH 38/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index e7ac273cb..85f59c2e5 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -230,7 +230,7 @@ render() { // Зазвичай це значення стану або методи екземпляра const injectedProp = someStateOrInstanceMethod; - // Передайте props до обгорнутого компонента + // Передайте пропси до обгорнутого компонента return ( Date: Mon, 20 Jan 2020 09:06:09 +0200 Subject: [PATCH 39/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 85f59c2e5..419bfe018 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -242,7 +242,7 @@ render() { Ця угода допомагає забезпечити максимальну гнучкість та можливість повторного використання КВП. -## Угода: максимізація композиційності {#convention-maximizing-composability} +## Конвенція: максимізація композиційності {#convention-maximizing-composability} Не всі КВП виглядають однаково. Іноді вони приймають лише один аргумент — компонент, що буде обгорнений: From 93d11f9ab1e0e2a1e8e55f3386eab8162d4793f5 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:06:21 +0200 Subject: [PATCH 40/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 419bfe018..7e108d350 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -181,7 +181,8 @@ function logProps(InputComponent) { console.log('Current props: ', this.props); console.log('Next props: ', nextProps); }; - // Якщо ми повертаємо лише той самий отриманий компонент - це натяк, що він був мутований + // Якщо ми повертаємо лише той самий отриманий компонент - це натяк, що він + // був мутований return InputComponent; } From 02399061c19a0cf9a082361e576eb3d1082d8a05 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:06:35 +0200 Subject: [PATCH 41/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 7e108d350..7fdefb8ef 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -295,7 +295,7 @@ const EnhancedComponent = enhance(WrappedComponent) Ви можете знайти допоміжну функцію `compose` у багатьох сторонніх бібліотеках, включаючи lodash (під назвою [`lodash.flowRight`](https://lodash.com/docs/#flowRight)), [Redux](https://redux.js.org/api/compose) та [Ramda](https://ramdajs.com/docs/#compose). -## Угода: повертайте ім’я обгорнутого компонента для легшого дебагу {#convention-wrap-the-display-name-for-easy-debugging} +## Конвенція: повертайте ім’я обгорнутого компонента для легшого дебагу {#convention-wrap-the-display-name-for-easy-debugging} Створений КВП компонент-контейнер відображається в [React Developer Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат КВП. From 4cecffbce5e249e0e39f32ce449258996ed0670f Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:06:48 +0200 Subject: [PATCH 42/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index 7fdefb8ef..cf4c20d0e 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -297,7 +297,7 @@ const EnhancedComponent = enhance(WrappedComponent) ## Конвенція: повертайте ім’я обгорнутого компонента для легшого дебагу {#convention-wrap-the-display-name-for-easy-debugging} -Створений КВП компонент-контейнер відображається в [React Developer Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат КВП. +Створений КВП компонент-контейнер відображається у [React Developer Tools](https://github.com/facebook/react-devtools), як і будь-який інший компонент. Для того, щоб полегшити процес налагодження, визначте відображуване ім’я, яке повідомляє, що це результат КВП. Найпоширеніший прийом - обгортати відображуване ім’я загорнутого компонента. Отже, якщо ваш компонент вищого порядку названий `withSubscription`, а відображене ім’я загорнутого компонента - `CommentList`, визначте відображуване ім'я як `WithSubscription(CommentList)`: From 5ad5d62518774a388b77009c0aef32ab77808ae8 Mon Sep 17 00:00:00 2001 From: mikhailnetkachev-halolab <58465344+mikhailnetkachev-halolab@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:07:00 +0200 Subject: [PATCH 43/43] Update content/docs/higher-order-components.md Co-Authored-By: Volodymyr Klymenko --- content/docs/higher-order-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/higher-order-components.md b/content/docs/higher-order-components.md index cf4c20d0e..216347d9f 100644 --- a/content/docs/higher-order-components.md +++ b/content/docs/higher-order-components.md @@ -322,7 +322,7 @@ function getDisplayName(WrappedComponent) { Алгоритм порівняння React, що відомий як reconciliation (або узгодження), використовує перевірку на тотожність компонента, щоб визначити, чи слід оновити існуюче піддерево компонентів або слід знищити його та змонтувати нове. Якщо компонент, що був повернений рендер-методом, ідентичний (`===`) попередньому результату, React рекурсивно оновлює піддерева, порівнюючи його з новим. Якщо вони не тотожні, то попереднє піддерево буде повністю розмонтовано. -Зазвичай Вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що ви не можете застосувати КВП до компонента в рендер-методі іншого компонента: +Зазвичай вам не потрібно думати про це. Однак, це важливо для компонента вищого порядку, оскільки це означає, що ви не можете застосувати КВП до компонента в рендер-методі іншого компонента: ```js render() {