Синтаксис хуков
Синтаксис хуков — это первоклассная поддержка синтаксиса и проверки типов для хуков React. Она добавляет хуки в язык React как отдельные сущности, синтаксически и семантически отличающиеся от обычных функций, и использует Flow, чтобы гарантировать соблюдение Правил React.
Основное использование
Главное отличие между функцией и хуком — ключевое слово hook:
import {useState, useEffect} from 'react';
hook useOnlineStatus(initial: boolean): boolean {
const [isOnline, setIsOnline] = useState(initial);
useEffect(() => {
// ...
}, []);
return isOnline;
} Хуки можно вызывать так же, как обычные функции:
import * as React from 'react';
hook useOnlineStatus(): boolean {
return true;
}
component StatusBar() {
const isOnline = useOnlineStatus();
return <h1>{isOnline ? '✅ Online' : '❌ Disconnected'}</h1>;
} Хуки можно экспортировать так же, как обычные функции:
export hook useNamedExportedHook(): boolean {
return true;
}
export default hook useDefaultExportedHook(): boolean {
return true;
} Аннотации типов хуков
В некоторых случаях может потребоваться определить значение как имеющее тип хука. Поскольку типы функций и типы хуков несовместимы (подробнее об этом ниже!), мы вводим новый синтаксис для аннотаций типов хуков: это существующая аннотация типа функции с добавленным перед ней hook.
declare function experiment(name: string): boolean;
declare hook useOnlineStatus(x: boolean): boolean;
declare hook useAlwaysOnlineStatus(x: boolean): boolean;
export const useGKOnlineStatus: hook (boolean) => boolean =
experiment('show_online_status')
? useOnlineStatus
: useAlwaysOnlineStatus Соблюдение Правил React с помощью синтаксиса хуков
Синтаксис хуков позволяет однозначно различать хуки и прочие функции на уровне синтаксиса. Flow использует эту информацию, чтобы проверять соблюдение ряда правил хуков и в целом Правил React.
Предотвращение небезопасного изменения данных
Согласно Правилам React, во время рендеринга компонента нельзя читать или изменять рефы, а возвращаемое значение других хуков (особенно useState) вообще нельзя безопасно изменять напрямую. Теперь, когда Flow распознаёт хуки как первоклассную концепцию, во многих случаях он может выявлять такие проблемы и сообщать об ошибках заранее, вместо того чтобы полагаться на тестирование.
import {useState, useEffect, useRef} from 'react';
import * as React from 'react';
component MyComponent() {
const ref = useRef<?number>(null);
const [state, setState] = useState<{ val: number }>({val: 0});
state.val = 42; // Error: cannot mutate return value of hook
return (
<div>
{ref.current /* Error: cannot read ref during rendering */}
</div>
);
} В настоящее время Flow запрещает изменять свойства компонента внутри самого компонента. Синтаксис хуков позволяет распространить эту проверку на хуки и обнаруживать недопустимые изменения внутри объявлений хуков, сообщая об ошибках.
hook useIllegalMutation(values: Array<number>) {
values[0] = 42; // Error: mutating argument to hook
// ...
} Предотвращение условных вызовов хуков
Правила хуков запрещают вызывать хуки условно. Это проверяет плагин ESLint для React, а теперь Flow также будет выявлять такие нарушения.
hook useOnlineStatus(): boolean {
return true;
}
component StatusBar(shouldShowOnlineStatus: boolean) {
if (shouldShowOnlineStatus) {
const onlineStatus = useOnlineStatus(); // Error
}
return null;
} Предотвращение смешения хуков и функций
Различие между хуками и обычными функциями отражено в системе типов Flow. Из-за разных требований, которым должны соответствовать хуки и функции, Flow выдаст ошибку, если передать значение, определённое как хук, туда, где ожидается тип функции, или обычную функцию JavaScript туда, где ожидается хук.
Отслеживание принадлежности к хукам как части типа функции позволяет Flow выявлять нарушения, недоступные для линтера на основе AST (например, eslint-plugin-react-hooks): в месте вызова нет синтаксических признаков того, что вызываемая функция будет использовать fn как хук, поэтому синтаксическая проверка не сможет обнаружить проблему. Диагностика становится возможной благодаря информации о типах, которую Flow отслеживает для всей программы.
import {useState, useEffect} from 'react';
hook useMultiplier(x: number): number {
const [y, setY] = useState(1);
useEffect(() => { setY(0) })
return x * y;
}
component Mapper(args: Array<number>) {
const multArgs = args.map(useMultiplier); // Error [react-rule-hook-incompatible]
return multArgs;
} Кроме того, Flow проверяет, что вызываемые функции с именами, похожими на имена хуков, внутри хуков и компонентов действительно являются хуками. Также Flow гарантирует, что вызываемые функции внутри объявлений обычных функций никогда не являются хуками.
hook useHook() { return null }
function regularJavascript() {
const x = useHook(); // Error: cannot call a hook outside of a component or hook
}
component Component() {
const renamedHook = useHook;
renamedHook(); // Error: cannot call a hook whose name does not begin with `use`
return null;
} Доступность
Синтаксис хуков включён по умолчанию начиная с Flow v0.317 тем же параметром, который включает Синтаксис компонентов. В более старых версиях добавьте component_syntax=true в раздел [options] вашего файла .flowconfig.
См. также
- Обобщённые типы — параметры обобщённых типов, используемые в сигнатурах хуков
- Функции — для хуков действуют правила типизации, сходные с правилами для функций
© 2013–present Facebook Inc.
Licensed under the MIT License.
https://flow.org/en/docs/react/hook-syntax