|
1 | 1 | ---
|
2 | 2 | id: forwarding-refs
|
3 |
| -title: Forwarding Refs |
| 3 | +title: Перенаправление рефов |
4 | 4 | permalink: docs/forwarding-refs.html
|
5 | 5 | ---
|
6 | 6 |
|
7 |
| -Ref forwarding is a technique for automatically passing a [ref](/docs/refs-and-the-dom.html) through a component to one of its children. This is typically not necessary for most components in the application. However, it can be useful for some kinds of components, especially in reusable component libraries. The most common scenarios are described below. |
| 7 | +Перенаправление рефов позволяет автоматически передавать [реф](/docs/refs-and-the-dom.html) компонента одному из его дочерних элементов. Большинству компонентов перенаправление рефов не нужно, но оно может быть полезно, например, если вы пишете библиотеку. Рассмотрим наиболее частые сценарии. |
8 | 8 |
|
9 |
| -## Forwarding refs to DOM components {#forwarding-refs-to-dom-components} |
| 9 | +## Перенаправление рефов в DOM-компоненты {#forwarding-refs-to-dom-components} |
10 | 10 |
|
11 |
| -Consider a `FancyButton` component that renders the native `button` DOM element: |
| 11 | +Допустим, у нас есть компонент `FancyButton`, который рендерит нативный DOM-элемент `button`: |
12 | 12 | `embed:forwarding-refs/fancy-button-simple.js`
|
13 | 13 |
|
14 |
| -React components hide their implementation details, including their rendered output. Other components using `FancyButton` **usually will not need to** [obtain a ref](/docs/refs-and-the-dom.html) to the inner `button` DOM element. This is good because it prevents components from relying on each other's DOM structure too much. |
| 14 | +React-компоненты скрывают свои детали реализации, в том числе результат рендеринга. Реф элемента `button` из `FancyButton` **обычно и не требуется** другим компонентам. Это хорошо, поскольку такой подход не даёт компонентам излишне полагаться на структуру DOM друг друга. |
15 | 15 |
|
16 |
| -Although such encapsulation is desirable for application-level components like `FeedStory` or `Comment`, it can be inconvenient for highly reusable "leaf" components like `FancyButton` or `MyTextInput`. These components tend to be used throughout the application in a similar manner as a regular DOM `button` and `input`, and accessing their DOM nodes may be unavoidable for managing focus, selection, or animations. |
| 16 | +Такая инкапсуляция хорошо подходит компонентам, которые описывают некую законченную часть приложения, например, `FeedStory` или `Comment`. А вот в «маленьких», часто переиспользуемых компонентах, таких как `FancyButton` или `MyTextInput`, она может быть неудобной. Чтобы управлять фокусом, выделением и анимациями этих компонентов, придётся получить доступ к их DOM-узлам. |
17 | 17 |
|
18 |
| -**Ref forwarding is an opt-in feature that lets some components take a `ref` they receive, and pass it further down (in other words, "forward" it) to a child.** |
| 18 | +**Перенаправление рефов позволяет взять `ref` из атрибутов компонента, и передать («перенаправить») его одному из дочерних компонентов.** |
19 | 19 |
|
20 |
| -In the example below, `FancyButton` uses `React.forwardRef` to obtain the `ref` passed to it, and then forward it to the DOM `button` that it renders: |
| 20 | +В данном примере мы используем `React.forwardRef` в компоненте `FancyButton`, чтобы получить реф и передать его в дочерний DOM-элемент `button`. |
21 | 21 |
|
22 | 22 | `embed:forwarding-refs/fancy-button-simple-ref.js`
|
23 | 23 |
|
24 |
| -This way, components using `FancyButton` can get a ref to the underlying `button` DOM node and access it if necessary—just like if they used a DOM `button` directly. |
| 24 | +Таким образом, когда мы будем применять `FancyButton` в других компонентах, мы сможем получить реф находящегося в нём DOM-узла `button` и использовать его так же, как если бы мы рендерили непосредственно `button`. |
25 | 25 |
|
26 |
| -Here is a step-by-step explanation of what happens in the above example: |
| 26 | +Рассмотрим этот пример пошагово: |
27 | 27 |
|
28 |
| -1. We create a [React ref](/docs/refs-and-the-dom.html) by calling `React.createRef` and assign it to a `ref` variable. |
29 |
| -1. We pass our `ref` down to `<FancyButton ref={ref}>` by specifying it as a JSX attribute. |
30 |
| -1. React passes the `ref` to the `(props, ref) => ...` function inside `forwardRef` as a second argument. |
31 |
| -1. We forward this `ref` argument down to `<button ref={ref}>` by specifying it as a JSX attribute. |
32 |
| -1. When the ref is attached, `ref.current` will point to the `<button>` DOM node. |
| 28 | +1. Мы создаём [реф](/docs/refs-and-the-dom.html), вызвав `React.createRef` и записываем его в переменную `ref`. |
| 29 | +1. Мы передаём переменную `ref` в `<FancyButton ref={ref}>`, указывая её в JSX-атрибуте. |
| 30 | +1. React передаёт `ref` в функцию `(props, ref) => ...` внутри `forwardRef` в качестве второго аргумента. |
| 31 | +1. Мы передаём аргумент `ref` дальше в `<button ref={ref}>`, указывая его в JSX-атрибуте. |
| 32 | +1. После привязки рефа `ref.current` будет указывать на DOM-узел `<button>`. |
33 | 33 |
|
34 |
| ->Note |
| 34 | +>Примечание |
35 | 35 | >
|
36 |
| ->The second `ref` argument only exists when you define a component with `React.forwardRef` call. Regular function or class components don't receive the `ref` argument, and ref is not available in props either. |
| 36 | +>Второй аргумент `ref` существует только в том случае, если вы создаёте компонент через функцию `React.forwardRef`. Обычные функциональные или классовые компоненты не получают `ref` в качестве аргумента или пропа. |
37 | 37 | >
|
38 |
| ->Ref forwarding is not limited to DOM components. You can forward refs to class component instances, too. |
| 38 | +>Перенаправить реф можно не только в DOM-компонент, но и в экземпляр классового компонента. |
39 | 39 |
|
40 |
| -## Note for component library maintainers {#note-for-component-library-maintainers} |
| 40 | +## Примечание для разработчиков библиотек компонентов {#note-for-component-library-maintainers} |
41 | 41 |
|
42 |
| -**When you start using `forwardRef` in a component library, you should treat it as a breaking change and release a new major version of your library.** This is because your library likely has an observably different behavior (such as what refs get assigned to, and what types are exported), and this can break apps and other libraries that depend on the old behavior. |
| 42 | +**Если вы впервые использовали `forwardRef` в компоненте библиотеки, то следует сделать новую версию мажорной и указать на обратную несовместимость изменений.** Причина этого в том, что, скорее всего, компонент станет вести себя заметно иначе (например, изменится тип экспортируемых данных и элемент, к которому привязан реф), в результате чего приложения и другие библиотеки, полагающиеся на старое поведение, перестанут работать. |
43 | 43 |
|
44 |
| -Conditionally applying `React.forwardRef` when it exists is also not recommended for the same reasons: it changes how your library behaves and can break your users' apps when they upgrade React itself. |
| 44 | +По этой же причине мы рекомендуем не вызывать `React.forwardRef` условно (то есть сперва проверяя, что эта функция определена). Это изменит поведение вашей библиотеки и приложения ваших пользователей могут перестать работать при обновлении самого React. |
| 45 | +## Перенаправление рефов в компонентах высшего порядка {#forwarding-refs-in-higher-order-components} |
45 | 46 |
|
46 |
| -## Forwarding refs in higher-order components {#forwarding-refs-in-higher-order-components} |
47 |
| - |
48 |
| -This technique can also be particularly useful with [higher-order components](/docs/higher-order-components.html) (also known as HOCs). Let's start with an example HOC that logs component props to the console: |
| 47 | +Особенно полезным перенаправление может оказаться в [компонентах высшего порядка](/docs/higher-order-components.html) (также известных как HOC). Начнём с примера, в котором HOC выводит пропсы компонента в консоль: |
49 | 48 | `embed:forwarding-refs/log-props-before.js`
|
50 | 49 |
|
51 |
| -The "logProps" HOC passes all `props` through to the component it wraps, so the rendered output will be the same. For example, we can use this HOC to log all props that get passed to our "fancy button" component: |
| 50 | +Компонент высшего порядка `logProps` передаёт все пропсы в компонент, который он оборачивает, так что рендерить они будут одно и то же. С его помощью мы будем выводить в консоль все пропсы, переданные в наш компонент с кнопкой: |
52 | 51 | `embed:forwarding-refs/fancy-button.js`
|
53 | 52 |
|
54 |
| -There is one caveat to the above example: refs will not get passed through. That's because `ref` is not a prop. Like `key`, it's handled differently by React. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component. |
| 53 | +Обратите внимание, что в этом примере не будут передаваться рефы. Так происходит, потому что `ref` это не проп. Подобно `key`, React обрабатывает `ref` особым образом. Если вы укажите реф для HOC, он привяжется к ближайшему к корню контейнера, а не к переданному в HOC компоненту. |
55 | 54 |
|
56 |
| -This means that refs intended for our `FancyButton` component will actually be attached to the `LogProps` component: |
| 55 | +Следовательно, рефы, предназначенные для компонента `FancyButton`, окажутся привязанными к компоненту `LogProps`: |
57 | 56 | `embed:forwarding-refs/fancy-button-ref.js`
|
58 | 57 |
|
59 |
| -Fortunately, we can explicitly forward refs to the inner `FancyButton` component using the `React.forwardRef` API. `React.forwardRef` accepts a render function that receives `props` and `ref` parameters and returns a React node. For example: |
| 58 | +К счастью, мы можем явно перенаправить рефы на компонент `FancyButton` внутри HOC при помощи API `React.forwardRef`. В `React.forwardRef` передаётся функция рендеринга, которая принимает аргументы `props` и `ref`, а возвращает узел React. Например: |
60 | 59 | `embed:forwarding-refs/log-props-after.js`
|
61 | 60 |
|
62 |
| -## Displaying a custom name in DevTools {#displaying-a-custom-name-in-devtools} |
| 61 | +## Изменение названия в инструментах разработки {#displaying-a-custom-name-in-devtools} |
63 | 62 |
|
64 |
| -`React.forwardRef` accepts a render function. React DevTools uses this function to determine what to display for the ref forwarding component. |
| 63 | +В `React.forwardRef` передаётся функция рендеринга. Эта функция определяет, как будет называться компонент в инструментах разработки. |
65 | 64 |
|
66 |
| -For example, the following component will appear as "*ForwardRef*" in the DevTools: |
| 65 | +Например, вот этот компонент будет называться «*ForwardRef*»: |
67 | 66 |
|
68 | 67 | `embed:forwarding-refs/wrapped-component.js`
|
69 | 68 |
|
70 |
| -If you name the render function, DevTools will also include its name (e.g. "*ForwardRef(myFunction)*"): |
| 69 | +Если присвоить имя функции рендеринга, то оно появится в названии компонента в инструментах разработки (например, «*ForwardRef(myFunction)*»): |
71 | 70 |
|
72 | 71 | `embed:forwarding-refs/wrapped-component-with-function-name.js`
|
73 | 72 |
|
74 |
| -You can even set the function's `displayName` property to include the component you're wrapping: |
| 73 | +Можно даже назначить функции свойство `displayName` и указать в нём, какой именно компонент обёрнут в HOC: |
75 | 74 |
|
76 | 75 | `embed:forwarding-refs/customized-display-name.js`
|
0 commit comments