From 003f177e46b2edef59d5c6f59291d818e4385e49 Mon Sep 17 00:00:00 2001 From: Michael Babin Date: Mon, 25 Mar 2019 18:30:06 +0200 Subject: [PATCH 1/5] WIP: useState and useEffect --- content/docs/hooks-reference.md | 98 ++++++++++++++++----------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index 98c2e14c0..17127c1b2 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -1,22 +1,22 @@ --- id: hooks-reference -title: Hooks API Reference +title: API-довідник хуків permalink: docs/hooks-reference.html prev: hooks-custom.html next: hooks-faq.html --- -*Hooks* are a new addition in React 16.8. They let you use state and other React features without writing a class. +*Хуки* — це новинка в React 16.8. Вони дозволяють вам використовувати стан та інші можливості React без написання класу. -This page describes the APIs for the built-in Hooks in React. +Ця сторінка описує API для вбудованих у React хуків. -If you're new to Hooks, you might want to check out [the overview](/docs/hooks-overview.html) first. You may also find useful information in the [frequently asked questions](/docs/hooks-faq.html) section. +Якщо ви новачок у хуках, ви можете спочатку переглянути [огляд](/docs/hooks-overview.html). Також ви можете знайти корисну інформацію у розділі [часто задаваних питань](/docs/hooks-faq.html). -- [Basic Hooks](#basic-hooks) +- [Базові Хуки](#basic-hooks) - [`useState`](#usestate) - [`useEffect`](#useeffect) - [`useContext`](#usecontext) -- [Additional Hooks](#additional-hooks) +- [Додаткові Хуки](#additional-hooks) - [`useReducer`](#usereducer) - [`useCallback`](#usecallback) - [`useMemo`](#usememo) @@ -25,7 +25,7 @@ If you're new to Hooks, you might want to check out [the overview](/docs/hooks-o - [`useLayoutEffect`](#uselayouteffect) - [`useDebugValue`](#usedebugvalue) -## Basic Hooks {#basic-hooks} +## Базові хуки {#basic-hooks} ### `useState` {#usestate} @@ -33,25 +33,25 @@ If you're new to Hooks, you might want to check out [the overview](/docs/hooks-o const [state, setState] = useState(initialState); ``` -Returns a stateful value, and a function to update it. +Повертає значення стану та функцію, що оновлює його. -During the initial render, the returned state (`state`) is the same as the value passed as the first argument (`initialState`). +Під час початкового рендеру повернутий стан (`state`) співпадає зі значенням, переданим у першому аргументі (`initialState`). -The `setState` function is used to update the state. It accepts a new state value and enqueues a re-render of the component. +Функція `setState` використовується для оновлення стану. Вона приймає значення нового стану і ставить у чергу повторний рендер компонента. ```js setState(newState); ``` -During subsequent re-renders, the first value returned by `useState` will always be the most recent state after applying updates. +Упродовж наступних повторних рендерів, перше значення, повернуте `useState`, завжди буде у актуальному стані при здійсненні оновлень. ->Note +>Примітка > ->React guarantees that `setState` function identity is stable and won't change on re-renders. This is why it's safe to omit from the `useEffect` or `useCallback` dependency list. +>React гарантує, що функція `setState` зберігає ідентичність і не змінюється під час повторних рендерів. Саме тому, ви можете безпечно пропускати її включення до списків залежностей хуків `useEffect` чи `useCallback`. -#### Functional updates {#functional-updates} +#### Функціональні оновлення {#functional-updates} -If the new state is computed using the previous state, you can pass a function to `setState`. The function will receive the previous value, and return an updated value. Here's an example of a counter component that uses both forms of `setState`: +Якщо наступний стан обчислюється з використанням попереднього, ви можете передати функцію до `setState`. Функція отримає попереднє значення і поверне оновлене. Ось приклад компонента лічильника, що використовує обидві форми `setState`: ```js function Counter({initialCount}) { @@ -59,7 +59,7 @@ function Counter({initialCount}) { return ( <> Count: {count} - + @@ -67,24 +67,24 @@ function Counter({initialCount}) { } ``` -The "+" and "-" buttons use the functional form, because the updated value is based on the previous value. But the "Reset" button uses the normal form, because it always sets the count back to 0. +Кнопки "+" та "-" використовують функціональну форму, тому що оновлене значення базується на попередньому. В той же час кнопка "Скинути" використовує нормальну форму, тому що вона завжди скидає значення назад до 0. -> Note +> Примітка > -> Unlike the `setState` method found in class components, `useState` does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax: +> На відміну від методу `setState` у класових компонентах, `useState` не об'єднує оновлювані об'єкти автоматично. Ви можете відтворити таку поведінку, комбінуючи функціональну форму оновлення і синтаксис розширення об'єктів: > > ```js > setState(prevState => { -> // Object.assign would also work +> // Object.assign також спрацює > return {...prevState, ...updatedValues}; > }); > ``` > -> Another option is `useReducer`, which is more suited for managing state objects that contain multiple sub-values. +> Іншим варіантом може бути хук `useReducer`, котрий більш підходть для керування об'єктами стану, що містять багато інших значень. -#### Lazy initial state {#lazy-initial-state} +#### Лінива ініціалізація стану {#lazy-initial-state} -The `initialState` argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render: +Аргумент `initialState` — це стан, що використовується протягом початкового рендеру. При наступних рендерах воно не враховується. Якщо початковий стан є результатом вартісних обчислень, ви можете замість нього надати функцію, що буде виконана лише під час початкового рендеру: ```js const [state, setState] = useState(() => { @@ -93,11 +93,11 @@ const [state, setState] = useState(() => { }); ``` -#### Bailing out of a state update {#bailing-out-of-a-state-update} +#### Припинення оновлення стану {#bailing-out-of-a-state-update} -If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the [`Object.is` comparison algorithm](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) +Якщо ви оновите стан хука значенням, що дорівнює поточному, React вийде з хука без рендерингу дочірніх елементів чи запуску ефектів. (React використовує [алгоритм порівняння `Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) -Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go "deeper" into the tree. If you're doing expensive calculations while rendering, you can optimize them with `useMemo`. +Зверніть увагу, що React може знадобитись відрендерити конкретний компонент перед припиненням оновлення. Це не повинно викликати занепокоєння, тому що React необов'язково опуститься "глибше" в дерево. Якщо ви здійснюєте вартісні обчислення під час рендерингу, ви можете оптимізувати їх, використавши `useMemo`. ### `useEffect` {#useeffect} @@ -105,45 +105,45 @@ Note that React may still need to render that specific component again before ba useEffect(didUpdate); ``` -Accepts a function that contains imperative, possibly effectful code. +Приймає функцію, що містить імперативний, можливо з ефектами, код. -Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React's _render phase_). Doing so will lead to confusing bugs and inconsistencies in the UI. +Зміни, підписки, таймери, логування та інші побічні ефекти не дозволяються всередині основного тіла функціонального компонента (яке ми називаємо _етап рендеру_). Це призводить до заплутаних помилок та невідповідностям у користувацькому інтерфейсі. -Instead, use `useEffect`. The function passed to `useEffect` will run after the render is committed to the screen. Think of effects as an escape hatch from React's purely functional world into the imperative world. +Натомість застосовуйте `useEffect`. Функція, передана в `useEffect`, буде запущена після того, як вивід рендеру з'явиться на екрані. Думайте про ефекти як про засіб втечі з чисто функціонального світу React до світу імперативів. -By default, effects run after every completed render, but you can choose to fire it [only when certain values have changed](#conditionally-firing-an-effect). +За замовчуванням ефекти запускаються після кожного завершеного рендеру, але ви можете запускати їх, наприклад, коли [змінились тільки певні значення](#conditionally-firing-an-effect). -#### Cleaning up an effect {#cleaning-up-an-effect} +#### Очищення ефектів {#cleaning-up-an-effect} -Often, effects create resources that need to be cleaned up before the component leaves the screen, such as a subscription or timer ID. To do this, the function passed to `useEffect` may return a clean-up function. For example, to create a subscription: +Ефекти часто створюють ресурси, пам'ять після використання яких, має бути звільнена перед тим, як компонент зникне з екрану, наприклад, підписка або ідентифікатор таймера. Щоб це зробити, функція, передана у `useEffect`, може повернути функцію очищення. Наприклад, щоб створити підписку: ```js useEffect(() => { const subscription = props.source.subscribe(); return () => { - // Clean up the subscription + // Очистити підписку subscription.unsubscribe(); }; }); ``` -The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the **previous effect is cleaned up before executing the next effect**. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section. +Функція очищення буде запущена перед видаленням компонента з інтерфейсу користувача, щоб запобігти витокам пам'яті. Крім цього, якщо компонент рендериться багато разів (що доволі типово), **попередній ефект буде очищено до виконання наступного**. У нашому прикладі це означає, що нова підписка створюється на кожному оновленні. Зверніться до наступного розділу, щоб дізнатися, як цього можна уникнути. -#### Timing of effects {#timing-of-effects} +#### Порядок спрацювання ефектів {#timing-of-effects} -Unlike `componentDidMount` and `componentDidUpdate`, the function passed to `useEffect` fires **after** layout and paint, during a deferred event. This makes it suitable for the many common side effects, like setting up subscriptions and event handlers, because most types of work shouldn't block the browser from updating the screen. +На відміну від `componentDidMount` і `componentDidUpdate`, функція передана в `useEffect` запускається **після** розмітки та рендеру, протягом відкладеної події. Це робить хук підходящим для багатьох поширених побічних ефектів, таких як налаштування підписок та обробників подій, оскільки більшість типів роботи не повинні блокувати оновлення екрану браузером. -However, not all effects can be deferred. For example, a DOM mutation that is visible to the user must fire synchronously before the next paint so that the user does not perceive a visual inconsistency. (The distinction is conceptually similar to passive versus active event listeners.) For these types of effects, React provides one additional Hook called [`useLayoutEffect`](#uselayouteffect). It has the same signature as `useEffect`, and only differs in when it is fired. +Проте не всі ефекти можуть бути відкладені. Наприклад, зміна DOM, що видима користувачу, має запуститись синхронно перед наступним рендером, щоб користувач не помічав візуальної невідповідності. (Ця відмінність концептально подібна до відмінності між пасивними та активними слухачами подій.) Для таких різновидів ефектів React надає додатковий хук, що зветься [`useLayoutEffect`](#uselayouteffect). Він має таку ж сигнатуру, як і `useEffect`, але відрізняється умовою запуску. -Although `useEffect` is deferred until after the browser has painted, it's guaranteed to fire before any new renders. React will always flush a previous render's effects before starting a new update. +Незважаючи на те, що `useEffect` відкладається допоки браузер не виконає відображення, він гарантовано спрацює перед кожним новим рендером. React завжди застосовує ефекти попереднього рендеру перед початком нового оновлення. -#### Conditionally firing an effect {#conditionally-firing-an-effect} +#### Умовне спрацювання ефекту {#conditionally-firing-an-effect} -The default behavior for effects is to fire the effect after every completed render. That way an effect is always recreated if one of its dependencies changes. +За замовчуванням ефекти спрацьовуються після кожного завершеного рендеру. Таким чином, ефект завжди створюється повторно при зміні одної з його залежностей. -However, this may be overkill in some cases, like the subscription example from the previous section. We don't need to create a new subscription on every update, only if the `source` props has changed. +Проте, у деяких випадках, це може бути надлишковим, так само як у прикладі з підпискою у попередньому розділі. Нам не потрібно створювати нову підписку для кожного оновлення, а лише тоді, коли змінився проп `source`. -To implement this, pass a second argument to `useEffect` that is the array of values that the effect depends on. Our updated example now looks like this: +Щоб реалізувати це, передайте другим аргументом до `useEffect` масив значень, від яких залежить ефект. Наш оновлений ефект тепер виглядає так: ```js useEffect( @@ -157,20 +157,20 @@ useEffect( ); ``` -Now the subscription will only be recreated when `props.source` changes. +Зараз підписка буде створена повторно лише при зміні `props.source`. ->Note +>Примітка > ->If you use this optimization, make sure the array includes **all values from the component scope (such as props and state) that change over time and that are used by the effect**. Otherwise, your code will reference stale values from previous renders. Learn more about [how to deal with functions](/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies) and what to do when the [array values change too often](/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often). +>Якщо ви використовуєте цю оптимізацію, впевніться, що масив включає **всі значення з області видимості компонента (такі як пропси чи стан), що можуть змінюватись протягом часу і використовуються ефектом**. Інакше, ваш код буде посилатись на застарілі значення з попередніх рендерів. Дізнайтеся більше про те, [як мати справу з функціями](/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies) та що робити, коли [значення масиву змінюються надто часто](/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often). > ->If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array (`[]`) as a second argument. This tells React that your effect doesn't depend on *any* values from props or state, so it never needs to re-run. This isn't handled as a special case -- it follows directly from how the dependencies array always works. +>Якщо ви хочете запустити ефект і очистити його лише раз (при монтуванні і розмонтуванні), ви можете передати другим аргументом порожній масив (`[]`). React буде вважати, що ваш ефект не залежить від *жодного* із значень пропсів чи стану, а тому не потребує повторного запуску. Це не оброблюється як особливий випадок, а напряму випливає з роботи масиву залежностей. > ->If you pass an empty array (`[]`), the props and state as inside the effect will always have their initial values. While passing `[]` as the second argument is closer to the familiar `componentDidMount` and `componentWillUnmount` mental model, there are usually [better](/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies) [solutions](/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often) to avoid re-running effects too often. Also, don't forget that React defers running `useEffect` until after the browser has painted, so doing extra work is less of a problem. +>Якщо ви передаєте порожній масив (`[]`), пропси і стан усередині ефекту будуть завжди мати їх початкові значення. Передача другим аргументом `[]`, нагадує модель роботи вже знайомих `componentDidMount` та `componentWillUnmount`, але зазвичай є [кращі](/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies) [рішення](/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often) для уникнення частих повторних викликів ефектів. Також не забудьте, що React відкладає виконання `useEffect` до моменту відображення вмісту браузером, а отже можливість виконання додаткової роботи не є істотною проблемою. > > ->We recommend using the [`exhaustive-deps`](https://github.com/facebook/react/issues/14920) rule as part of our [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks#installation) package. It warns when dependencies are specified incorrectly and suggests a fix. +>Ми радимо використовувати правило [`exhaustive-deps`](https://github.com/facebook/react/issues/14920), як частину нашого пакунку [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks#installation). Воно попереджує про те, що залежності вказані невірно і пропонує рішення. -The array of dependencies is not passed as arguments to the effect function. Conceptually, though, that's what they represent: every value referenced inside the effect function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically. +Масив залежностей не передається у якості аргументів до функції ефекту. Концептуально, проте, це те, що вони представляють: кожне значення, на яке посилається функція ефекту, також має з'являтись у масиві залежностей. У майбутньому, достатньо просунутий компілятор зможе створити цей масив автоматично. ### `useContext` {#usecontext} From 9a01115779e7cc6fb5755405c7f660c0d7035865 Mon Sep 17 00:00:00 2001 From: Michael Babin Date: Thu, 28 Mar 2019 22:07:41 +0200 Subject: [PATCH 2/5] Translated up to useLayoutEffect --- content/docs/hooks-reference.md | 108 ++++++++++++++++---------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index 17127c1b2..bef52ec43 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -178,27 +178,27 @@ useEffect( const value = useContext(MyContext); ``` -Accepts a context object (the value returned from `React.createContext`) and returns the current context value for that context. The current context value is determined by the `value` prop of the nearest `` above the calling component in the tree. +Приймає об'єкт контексту (значення, повернуте з `React.createContext`) і повертає поточне значення контексту для нього. Поточне значення контексту визначається пропом `value` найближчого ``, що знаходиться вище у дереві компонентів. -When the nearest `` above the component updates, this Hook will trigger a rerender with the latest context `value` passed to that `MyContext` provider. +Коли найближчий ``, що знаходиться вище поточного компонента, оновлюється, цей хук викличе повторний рендер з актуальним `value` контексту, переданим до провайдера `MyContext`. -Don't forget that the argument to `useContext` must be the *context object itself*: +Не забудьте про те, що аргумент переданий у `useContext`, повиен бути *власне об'єктом контексту*: - * **Correct:** `useContext(MyContext)` - * **Incorrect:** `useContext(MyContext.Consumer)` - * **Incorrect:** `useContext(MyContext.Provider)` + * **Правильно:** `useContext(MyContext)` + * **Неправильно:** `useContext(MyContext.Consumer)` + * **Неправильно:** `useContext(MyContext.Provider)` -A component calling `useContext` will always re-render when the context value changes. If re-rendering the component is expensive, you can [optimize it by using memoization](https://github.com/facebook/react/issues/15156#issuecomment-474590693). +Компонент, що викликає `useContext`, завжди повторно відрендериться при зміні значення контексту. Якщо повторний рендер є вартісною операцією, ви можете [оптимізувати його, використавши мемоізацію](https://github.com/facebook/react/issues/15156#issuecomment-474590693). ->Tip +>Порада > ->If you're familiar with the context API before Hooks, `useContext(MyContext)` is equivalent to `static contextType = MyContext` in a class, or to ``. +>Якщо ви ознайомились з API контексту до хуків, `useContext(MyContext)` є еквівалентним `static contextType = MyContext` у класі чи ``. > ->`useContext(MyContext)` only lets you *read* the context and subscribe to its changes. You still need a `` above in the tree to *provide* the value for this context. +>`useContext(MyContext)` дозволяє лише *читати* контекст і підписуватись на його зміни. Вам і досі необхідно мати `` вище у дереві, щоб *надати* цьому контексту значення. -## Additional Hooks {#additional-hooks} +## Додаткові хуки {#additional-hooks} -The following Hooks are either variants of the basic ones from the previous section, or only needed for specific edge cases. Don't stress about learning them up front. +Наступні хуки є або варіантами базових із розділу вище, або потрібні у вкрай специфічних випадках. Не потрібно вивчати їх наперед. ### `useReducer` {#usereducer} @@ -206,11 +206,11 @@ The following Hooks are either variants of the basic ones from the previous sect const [state, dispatch] = useReducer(reducer, initialArg, init); ``` -An alternative to [`useState`](#usestate). Accepts a reducer of type `(state, action) => newState`, and returns the current state paired with a `dispatch` method. (If you're familiar with Redux, you already know how this works.) +Є альтернативою [`useState`](#usestate). Приймає редюсер типу `(state, action) => newState` і повертає поточний стан у парі з методом `dispatch`. (Якщо ви знайомі з Redux, ви вже знаєте як це працює.) -`useReducer` is usually preferable to `useState` when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one. `useReducer` also lets you optimize performance for components that trigger deep updates because [you can pass `dispatch` down instead of callbacks](/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down). +Слід віддати перевагу `useReducer` над `useState`, коли ви маєте складну логіку стану, що включає багато значень чи ваш наступний стан залежить від попереднього. Крім того, `useReducer` дозволяє вам оптимізувати продуктивність для компонентів, що викликають глибокі оновлення, тому що [ви можете передати вниз `dispatch`, замість функцій повторного виклику](/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down). -Here's the counter example from the [`useState`](#usestate) section, rewritten to use a reducer: +Ось приклад лічильника із розділу [`useState`](#usestate), переписаний із використанням редюсера: ```js const initialState = {count: 0}; @@ -238,13 +238,13 @@ function Counter({initialState}) { } ``` ->Note +>Примітка > ->React guarantees that `dispatch` function identity is stable and won't change on re-renders. This is why it's safe to omit from the `useEffect` or `useCallback` dependency list. +>React гарантує, що функція `dispatch` зберігає ідентичність і не змінюється під час повторних рендерів. Саме тому, ви можете безпечно пропускати її включення до списків залежностей хуків `useEffect` чи `useCallback`. -#### Specifying the initial state {#specifying-the-initial-state} +#### Визначення початкового стану {#specifying-the-initial-state} -There’s two different ways to initialize `useReducer` state. You may choose either one depending on the use case. The simplest way to pass the initial state as a second argument: +Є два різних шляхи ініціалізації стану `useReducer`. Ви можете обрати будь-який, залежно від ситуації. Найпростіши м варіантом є передача початкового стану другим аргументом: ```js{3} const [state, dispatch] = useReducer( @@ -253,15 +253,15 @@ There’s two different ways to initialize `useReducer` state. You may choose ei ); ``` ->Note +>Примітка > ->React doesn’t use the `state = initialState` argument convention popularized by Redux. The initial value sometimes needs to depend on props and so is specified from the Hook call instead. If you feel strongly about this, you can call `useReducer(reducer, undefined, reducer)` to emulate the Redux behavior, but it's not encouraged. +>React не використовує `state = initialState` конвенцію про аргументи, популяризовану в Redux. Початкове значення часом залежить від пропсів, а тому вказується безпосередньо у виклиці хука. Якщо ви впевнені щодо цього, ви можете викликати `useReducer(reducer, undefined, reducer)`, щоб земулювати поведінку Redux, але робити так не рекомендується. -#### Lazy initialization {#lazy-initialization} +#### Лінива ініціалізація {#lazy-initialization} -You can also create the initial state lazily. To do this, you can pass an `init` function as the third argument. The initial state will be set to `init(initialArg)`. +Ви також можете ліниво створити початковий стан. Щоб зробити це, ви можете передати функцію `init` третім аргументом. Початковий стан буде встановлений у `init(initialArg)`. -It lets you extract the logic for calculating the initial state outside the reducer. This is also handy for resetting the state later in response to an action: +Це дозволить винести логіку обчислення початкового стану з редюсера. Також це може бути корисним при скиданні стану пізніше у відповідь на дію: ```js{1-3,11-12,19,24} function init(initialCount) { @@ -285,10 +285,10 @@ function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, initialCount, init); return ( <> - Count: {state.count} + Лічильник: {state.count} @@ -297,11 +297,11 @@ function Counter({initialCount}) { } ``` -#### Bailing out of a dispatch {#bailing-out-of-a-dispatch} +#### Припинення дії dispatch {#bailing-out-of-a-dispatch} -If you return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing effects. (React uses the [`Object.is` comparison algorithm](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) +Якщо ви повернете з хука редюсера значення, що дорівнює поточному стану, React вийде з нього без рендерингу дочірніх елементів чи запуску ефектів. (React використовує [алгоритм порівняння `Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) -Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go "deeper" into the tree. If you're doing expensive calculations while rendering, you can optimize them with `useMemo`. +Зверніть увагу, що React може знадобитись відрендерити конкретний компонент перед припиненням оновлення. Це не повинно викликати занепокоєння, тому що React необов'язково опуститься "глибше" в дерево. Якщо ви здійснюєте вартісні обчислення під час рендерингу, ви можете оптимізувати їх, використавши `useMemo`. ### `useCallback` {#usecallback} @@ -314,17 +314,17 @@ const memoizedCallback = useCallback( ); ``` -Returns a [memoized](https://en.wikipedia.org/wiki/Memoization) callback. +Повертає [мемоізовану](https://en.wikipedia.org/wiki/Memoization) функцію зворотнього виклику. -Pass an inline callback and an array of dependencies. `useCallback` will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders (e.g. `shouldComponentUpdate`). +Передайте вбудовану функцію зворотнього виклику і масив залежностей. `useCallback` поверне мемоізовану версію функції зворотнього виклику, котра змінюється лише тоді, коли одна з її залежностей змінюється. Це корисно при передачі фукцій зворотнього виклику до оптимізоваих дочірніх компонентів, що покладаються на рівність посилань задля уникнення непотрібних рендерів (наприклад, `shouldComponentUpdate`). -`useCallback(fn, deps)` is equivalent to `useMemo(() => fn, deps)`. +`useCallback(fn, deps)` є еквівалентом `useMemo(() => fn, deps)`. -> Note +> Примітка > -> The array of dependencies is not passed as arguments to the callback. Conceptually, though, that's what they represent: every value referenced inside the callback should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically. +> Масив залежностей не передається у якості аргументів до функції зворотнього виклику. Концептуально, проте, це те, що вони представляють: кожне значення, на яке посилається функція зворотнього виклику, також має з'являтись у масиві залежностей. У майбутньому, достатньо просунутий компілятор зможе створити цей масив автоматично. > -> We recommend using the [`exhaustive-deps`](https://github.com/facebook/react/issues/14920) rule as part of our [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks#installation) package. It warns when dependencies are specified incorrectly and suggests a fix. +> Ми радимо використовувати правило [`exhaustive-deps`](https://github.com/facebook/react/issues/14920), як частину нашого пакунку [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks#installation). Воно попереджує про те, що залежності вказані невірно і пропонує рішення. ### `useMemo` {#usememo} @@ -332,21 +332,21 @@ Pass an inline callback and an array of dependencies. `useCallback` will return const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); ``` -Returns a [memoized](https://en.wikipedia.org/wiki/Memoization) value. +Повертає [мемоізоване](https://en.wikipedia.org/wiki/Memoization) значення. -Pass a "create" function and an array of dependencies. `useMemo` will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render. +Передайте функцію "створення" та масив залежностей. `useMemo` повторно обчислить мемоізоване значення лише при зміні однієї з залежностей. Така оптимізація допомагає уникнути вартісних обчислень при кожному рендері. -Remember that the function passed to `useMemo` runs during rendering. Don't do anything there that you wouldn't normally do while rendering. For example, side effects belong in `useEffect`, not `useMemo`. +Пам'ятайте, що функція, передана до `useMemo`, запускається під час рендерингу. Не робіть у ній нічого, що ви зазвичай не робите під час рендерингу. Наприклад, побічні ефекти мають бути в `useEffect`, а не `useMemo`. -If no array is provided, a new value will be computed on every render. +Якщо масив не наданий, нове значення буде обчислене при кожному рендері. -**You may rely on `useMemo` as a performance optimization, not as a semantic guarantee.** In the future, React may choose to "forget" some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without `useMemo` — and then add it to optimize performance. +**Ви можете покластись на `useMemo` як на оптимізацію продуктивності, а не на семантичу гарантію.** У майбутньому React може вирішити "забути" деякі попередньо мемоізовані значення і переобчислити їх при наступному рендері, наприклад, для звілбнення пам'яті для компонентів поза областю видимості екрана. Напишіть ваш код так, щоб він працював без `useMemo`, а потім додайте його для оптимізації продуктивності. -> Note +> Примітка > -> The array of dependencies is not passed as arguments to the function. Conceptually, though, that's what they represent: every value referenced inside the function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically. +> Масив залежностей не передається у якості аргументів до функції. Концептуально, проте, це те, що вони представляють: кожне значення, на яке посилається функція, також має з'являтись у масиві залежностей. У майбутньому, достатньо просунутий компілятор зможе створити цей масив автоматично. > -> We recommend using the [`exhaustive-deps`](https://github.com/facebook/react/issues/14920) rule as part of our [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks#installation) package. It warns when dependencies are specified incorrectly and suggests a fix. +> Ми радимо використовувати правило [`exhaustive-deps`](https://github.com/facebook/react/issues/14920), як частину нашого пакунку [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks#installation). Воно попереджує про те, що залежності вказані невірно і пропонує рішення. ### `useRef` {#useref} @@ -354,35 +354,35 @@ If no array is provided, a new value will be computed on every render. const refContainer = useRef(initialValue); ``` -`useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument (`initialValue`). The returned object will persist for the full lifetime of the component. +`useRef` поверне змінний об'єкт рефу, властивість `.current` якого ініціалізується переданим аргументом (`initialValue`). Повернутий об'єкт буде зберігатись протягом всього часу життя компонента. -A common use case is to access a child imperatively: +Поширеним випадком використання є імперативний доступ до потомків: ```js function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { - // `current` points to the mounted text input element + // `current` вказує на примонтований елемент поля вводу тексту inputEl.current.focus(); }; return ( <> - + ); } ``` -Essentially, `useRef` is like a "box" that can hold a mutable value in its `.current` property. +По суті, `useRef` — це "коробка", що може містити змінне значення у власній властивості `.current`. -You might be familiar with refs primarily as a way to [access the DOM](/docs/refs-and-the-dom.html). If you pass a ref object to React with `
`, React will set its `.current` property to the corresponding DOM node whenever that node changes. +Рефи можуть бути вам знайомими перш за все як [засіб доступу до DOM](/docs/refs-and-the-dom.html). Якщо ви передасте об'єкт рефу у React як `
`, React встановить його властивість `.current` рівною значенню відповідного DOM вузла при будь-якій зміні цього вузла. -However, `useRef()` is useful for more than the `ref` attribute. It's [handy for keeping any mutable value around](/docs/hooks-faq.html#is-there-something-like-instance-variables) similar to how you'd use instance fields in classes. +Проте `useRef()` є корисним не тільки для простого атрибута `ref`. Він [згодиться для постійного збереження будь-якого змінного значення](/docs/hooks-faq.html#is-there-something-like-instance-variables) подібно до використання полей екземпляра класу. -This works because `useRef()` creates a plain JavaScript object. The only difference between `useRef()` and creating a `{current: ...}` object yourself is that `useRef` will give you the same ref object on every render. +Це можливо, тому що `useRef()` створює простий JavaScript-об'єкт. Єдина різниця між `useRef()` і створенням об'єкта `{current: ...}` власноруч полягає в тому, що `useRef` поверне один і той самий реф-об'єкт при кожному рендері. -Keep in mind that `useRef` *doesn't* notify you when its content changes. Mutating the `.current` property doesn't cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a [callback ref](/docs/hooks-faq.html#how-can-i-measure-a-dom-node) instead. +Пам'ятайте, що `useRef` *не* повідомляє вас про зміну свого вмісту. Зміна властивості `.current` не спричинить повторний рендер. Якщо ви хочете запустити деякий код під час того, як React прикріплює чи від'єднує реф до вузла DOM, то вам краще використати [реф зворотнього виклику](/docs/hooks-faq.html#how-can-i-measure-a-dom-node). ### `useImperativeHandle` {#useimperativehandle} @@ -391,7 +391,7 @@ Keep in mind that `useRef` *doesn't* notify you when its content changes. Mutati useImperativeHandle(ref, createHandle, [deps]) ``` -`useImperativeHandle` customizes the instance value that is exposed to parent components when using `ref`. As always, imperative code using refs should be avoided in most cases. `useImperativeHandle` should be used with `forwardRef`: +`useImperativeHandle` налаштовує значення екземпляра, яке надається батьківським компонентам при використанні `ref`. Як і зазвичай, у більшості випадків ви маєте уникати імперативного коду з використанням рефів. `useImperativeHandle` має використовуватись разом з `forwardRef`: ```js function FancyInput(props, ref) { @@ -406,7 +406,7 @@ function FancyInput(props, ref) { FancyInput = forwardRef(FancyInput); ``` -In this example, a parent component that renders `` would be able to call `fancyInputRef.current.focus()`. +У цьому прикладі батьківський компонент, що рендерить ``, матиме змогу викликати `fancyInputRef.current.focus()`. ### `useLayoutEffect` {#uselayouteffect} From 10fd201a8b7c95d8b36a8115523315ab99d47ad4 Mon Sep 17 00:00:00 2001 From: Michael Babin Date: Fri, 29 Mar 2019 09:29:42 +0200 Subject: [PATCH 3/5] Wrapped it up --- content/docs/hooks-reference.md | 34 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index bef52ec43..d55deaef5 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -410,17 +410,17 @@ FancyInput = forwardRef(FancyInput); ### `useLayoutEffect` {#uselayouteffect} -The signature is identical to `useEffect`, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside `useLayoutEffect` will be flushed synchronously, before the browser has a chance to paint. +Сигнатура хука є ідентичною `useEffect`, але він запускається синхронно після всіх змін DOM. Використовуйте це для читання розмітки з DOM і синхронних повторних рендерів. Оновлення, заплановані всередині `useLayoutEffect`, будуть виконані синхронно перед тим, як браузер відобразить їх. -Prefer the standard `useEffect` when possible to avoid blocking visual updates. +Віддайте перевагу використанню `useEffect`, коли це можливо, щоб уникнути блокування візуальних оновлень. -> Tip +> Порада > -> If you're migrating code from a class component, note `useLayoutEffect` fires in the same phase as `componentDidMount` and `componentDidUpdate`. However, **we recommend starting with `useEffect` first** and only trying `useLayoutEffect` if that causes a problem. +> Якщо ви переробляєте код класового компонента, зверніть увагу, що `useLayoutEffect` запускається на тому ж етапі, що й `componentDidMount` та `componentDidUpdate`. Однак **ми рекомендуємо розпочати з використання `useEffect`** і спробувати `useLayoutEffect` тільки при виникненні проблем. > ->If you use server rendering, keep in mind that *neither* `useLayoutEffect` nor `useEffect` can run until the JavaScript is downloaded. This is why React warns when a server-rendered component contains `useLayoutEffect`. To fix this, either move that logic to `useEffect` (if it isn't necessary for the first render), or delay showing that component until after the client renders (if the HTML looks broken until `useLayoutEffect` runs). +>Якщо ви використовуєте серверний рендеринг, пам'ятайте, що *ані* `useLayoutEffect`, ні `useEffect` не можуть бути запущені допоки JavaScript не завантажився. Саме тому React попереджує про те, що компонент, який рендериться на сервері, містить `useLayoutEffect`. Щоб виправити це, ви можете помістити цю логіку в `useEffect` (якщо вона не потрібна при першому рендері) або відкласти відображення цього компонента до моменту, коли відрендериться клієнт (якщо HTML виглядає невалідним до запуску `useLayoutEffect`). > ->To exclude a component that needs layout effects from the server-rendered HTML, render it conditionally with `showChild && ` and defer showing it with `useEffect(() => { setShowChild(true); }, [])`. This way, the UI doesn't appear broken before hydration. +>Щоб виключити компонент, що потребує ефектів розмітки, із відрендереного на сервері HTML, відрендеріть його умовно з допомогою `showChild && ` і відкладіть його відображення, використавши `useEffect(() => { setShowChild(true); }, [])`. Таким чином, інтерфейс користувача не буде виглядати неправильно перед гідратацією. ### `useDebugValue` {#usedebugvalue} @@ -428,9 +428,9 @@ Prefer the standard `useEffect` when possible to avoid blocking visual updates. useDebugValue(value) ``` -`useDebugValue` can be used to display a label for custom hooks in React DevTools. +`useDebugValue` може бути використаний для відображення мітки користувацьких хуків у інструментах розробника React. -For example, consider the `useFriendStatus` custom Hook described in ["Building Your Own Hooks"](/docs/hooks-custom.html): +Наприклад, ми маємо користувацький хук `useFriendStatus` описаний у розділі ["Створення користувацьких хуків"](/docs/hooks-custom.html): ```js{6-8} function useFriendStatus(friendID) { @@ -438,25 +438,25 @@ function useFriendStatus(friendID) { // ... - // Show a label in DevTools next to this Hook - // e.g. "FriendStatus: Online" - useDebugValue(isOnline ? 'Online' : 'Offline'); + // Показує мітку у інструментах розробника поруч з цим хуком + // наприклад, "FriendStatus: В мережі" + useDebugValue(isOnline ? 'В мережі' : 'Не в мережі'); return isOnline; } ``` -> Tip +> Порада > -> We don't recommend adding debug values to every custom Hook. It's most valuable for custom Hooks that are part of shared libraries. +> Ми не радимо додавати значення для налагодження до кожного користувацького хука. Вони найбільш цінні для користувацьких хуків, що є частиною загальнодоступних бібліотек. -#### Defer formatting debug values {#defer-formatting-debug-values} +#### Відкладення форматування значень для налагодження {#defer-formatting-debug-values} -In some cases formatting a value for display might be an expensive operation. It's also unnecessary unless a Hook is actually inspected. +У певних випадках, форматування значення для відображення може бути вартісною операцією. Також воно не потрібне у випадку, коли хук не перевіряється безпосередньо. -For this reason `useDebugValue` accepts a formatting function as an optional second parameter. This function is only called if the Hooks are inspected. It receives the debug value as a parameter and should return a formatted display value. +З цієї причини `useDebugValue` приймає функцію форматування у якості необов'язкового другого параметра. Ця функція викликається лише при перевірці хуків. Вона отримує налагоджувальне значення у якості параметра і повинна повертати форматоване значення для відображення. -For example a custom Hook that returned a `Date` value could avoid calling the `toDateString` function unnecessarily by passing the following formatter: +Для прикладу, користувацький хук, що повертає значення `Date`, може уникнути викликання функції `toDateString`, передавши наступну функцію форматування: ```js useDebugValue(date, date => date.toDateString()); From 6d78b921007c21cd40c85fe2a6882560ef5c72f4 Mon Sep 17 00:00:00 2001 From: Michael Babin Date: Sat, 30 Mar 2019 12:43:47 +0200 Subject: [PATCH 4/5] fix requested changes --- content/docs/hooks-reference.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index d55deaef5..2ec4d4814 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -43,7 +43,7 @@ const [state, setState] = useState(initialState); setState(newState); ``` -Упродовж наступних повторних рендерів, перше значення, повернуте `useState`, завжди буде у актуальному стані при здійсненні оновлень. +Упродовж наступних повторних рендерів, перше значення, повернуте `useState`, завжди буде в актуальному стані при здійсненні оновлень. >Примітка > @@ -80,7 +80,7 @@ function Counter({initialCount}) { > }); > ``` > -> Іншим варіантом може бути хук `useReducer`, котрий більш підходть для керування об'єктами стану, що містять багато інших значень. +> Іншим варіантом може бути хук `useReducer`, котрий більш підходить для керування об'єктами стану, що містять багато інших значень. #### Лінива ініціалізація стану {#lazy-initial-state} @@ -95,9 +95,9 @@ const [state, setState] = useState(() => { #### Припинення оновлення стану {#bailing-out-of-a-state-update} -Якщо ви оновите стан хука значенням, що дорівнює поточному, React вийде з хука без рендерингу дочірніх елементів чи запуску ефектів. (React використовує [алгоритм порівняння `Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) +Якщо ви оновите стан хука значенням, що дорівнює поточному, React вийде з хука без рендерингу дочірніх елементів чи запуску ефектів. (React використовує [алгоритм порівняння `Object.is`](https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) -Зверніть увагу, що React може знадобитись відрендерити конкретний компонент перед припиненням оновлення. Це не повинно викликати занепокоєння, тому що React необов'язково опуститься "глибше" в дерево. Якщо ви здійснюєте вартісні обчислення під час рендерингу, ви можете оптимізувати їх, використавши `useMemo`. +Зверніть увагу, що React-у може знадобитись відрендерити конкретний компонент перед припиненням оновлення. Це не повинно викликати занепокоєння, тому що React необов'язково опуститься "глибше" в дерево. Якщо ви здійснюєте вартісні обчислення під час рендерингу, ви можете оптимізувати їх, використавши `useMemo`. ### `useEffect` {#useeffect} @@ -244,7 +244,7 @@ function Counter({initialState}) { #### Визначення початкового стану {#specifying-the-initial-state} -Є два різних шляхи ініціалізації стану `useReducer`. Ви можете обрати будь-який, залежно від ситуації. Найпростіши м варіантом є передача початкового стану другим аргументом: +Є два різних шляхи ініціалізації стану `useReducer`. Ви можете обрати будь-який, залежно від ситуації. Найпростішим варіантом є передача початкового стану другим аргументом: ```js{3} const [state, dispatch] = useReducer( @@ -299,9 +299,9 @@ function Counter({initialCount}) { #### Припинення дії dispatch {#bailing-out-of-a-dispatch} -Якщо ви повернете з хука редюсера значення, що дорівнює поточному стану, React вийде з нього без рендерингу дочірніх елементів чи запуску ефектів. (React використовує [алгоритм порівняння `Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) +Якщо ви повернете з хука редюсера значення, що дорівнює поточному стану, React вийде з нього без рендерингу дочірніх елементів чи запуску ефектів. (React використовує [алгоритм порівняння `Object.is`](https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description).) -Зверніть увагу, що React може знадобитись відрендерити конкретний компонент перед припиненням оновлення. Це не повинно викликати занепокоєння, тому що React необов'язково опуститься "глибше" в дерево. Якщо ви здійснюєте вартісні обчислення під час рендерингу, ви можете оптимізувати їх, використавши `useMemo`. +Зверніть увагу, що React-у може знадобитись відрендерити конкретний компонент перед припиненням оновлення. Це не повинно викликати занепокоєння, тому що React необов'язково опуститься "глибше" в дерево. Якщо ви здійснюєте вартісні обчислення під час рендерингу, ви можете оптимізувати їх, використавши `useMemo`. ### `useCallback` {#usecallback} @@ -340,7 +340,7 @@ const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); Якщо масив не наданий, нове значення буде обчислене при кожному рендері. -**Ви можете покластись на `useMemo` як на оптимізацію продуктивності, а не на семантичу гарантію.** У майбутньому React може вирішити "забути" деякі попередньо мемоізовані значення і переобчислити їх при наступному рендері, наприклад, для звілбнення пам'яті для компонентів поза областю видимості екрана. Напишіть ваш код так, щоб він працював без `useMemo`, а потім додайте його для оптимізації продуктивності. +**Ви можете покластись на `useMemo` як на оптимізацію продуктивності, а не на семантичу гарантію.** У майбутньому React може вирішити "забути" деякі попередньо мемоізовані значення і переобчислити їх при наступному рендері, наприклад, для звільнення пам'яті для компонентів поза областю видимості екрана. Напишіть ваш код так, щоб він працював без `useMemo`, а потім додайте його для оптимізації продуктивності. > Примітка > @@ -376,7 +376,7 @@ function TextInputWithFocusButton() { По суті, `useRef` — це "коробка", що може містити змінне значення у власній властивості `.current`. -Рефи можуть бути вам знайомими перш за все як [засіб доступу до DOM](/docs/refs-and-the-dom.html). Якщо ви передасте об'єкт рефу у React як `
`, React встановить його властивість `.current` рівною значенню відповідного DOM вузла при будь-якій зміні цього вузла. +Рефи можуть бути вам знайомі перш за все як [засіб доступу до DOM](/docs/refs-and-the-dom.html). Якщо ви передасте об'єкт рефу у React як `
`, React встановить його властивість `.current` рівною значенню відповідного DOM вузла при будь-якій зміні цього вузла. Проте `useRef()` є корисним не тільки для простого атрибута `ref`. Він [згодиться для постійного збереження будь-якого змінного значення](/docs/hooks-faq.html#is-there-something-like-instance-variables) подібно до використання полей екземпляра класу. From 193cdbf4232d88e1fe39c1ce11a32bf0162fb86b Mon Sep 17 00:00:00 2001 From: Michael Babin Date: Sat, 30 Mar 2019 23:06:35 +0200 Subject: [PATCH 5/5] Don't translate FAQ --- content/docs/hooks-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index 2ec4d4814..c76c4db5c 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -10,7 +10,7 @@ next: hooks-faq.html Ця сторінка описує API для вбудованих у React хуків. -Якщо ви новачок у хуках, ви можете спочатку переглянути [огляд](/docs/hooks-overview.html). Також ви можете знайти корисну інформацію у розділі [часто задаваних питань](/docs/hooks-faq.html). +Якщо ви новачок у хуках, ви можете спочатку переглянути [огляд](/docs/hooks-overview.html). Також ви можете знайти корисну інформацію у розділі [FAQ](/docs/hooks-faq.html). - [Базові Хуки](#basic-hooks) - [`useState`](#usestate)