@skbkontur/react-sorge

React Fiber event listener

Usage no npm install needed!

<script type="module">
  import skbkonturReactSorge from 'https://cdn.skypack.dev/@skbkontur/react-sorge';
</script>

README

React Sorge

react-sorge - это пакет для отслеживания событий жизненного цикла в приложениях на React. Он позволяет отслеживать коммиты в fiber дерево, которые интерпретирует как следующие события: mount, update, unmount и mountRoot, updateRoot, unmountRoot. На каждое из событий можно повесить обработчик, который принимает объект(ы) типа Fiber.

За основу взята реализация расширения React Developer Tools, для связи с которым React использует специальный объект __REACT_DEVTOOLS_GLOBAL_HOOK__.
React связывается с ним во время инициализации, поэтому объект должен быть создан заранее.

Основные возможности

Подключение

Основная часть подключается строго до первого подключения пакета react-dom в приложении.
Достаточно ипортировать пакет таким образом:

// App.ts

import 'react-sorge';
import ReactDOM from 'react-dom';
...

Если служебный объект уже создан расширением React Developer Tools, то react-sorge подключается к нему.

Sorge

Объект Sorge содержит глобальные каналы событий. Каждый канал позволяет подписаться, отписаться и эмулировать событие.

import { Sorge, SorgeHandlerMount } from 'react-sorge';

const handler: SorgeHandlerMount = (fiber, parentFiber) => {};

Sorge.mount.on(handler);
Sorge.mount.off(handler);
Sorge.mount.emit(...args: [Fiber, Fiber?, Fiber?]);

Отписаться можно и так:

const off = Sorge.mount.on(handler);
off();

SorgeNode

Компонент <SorgeNode> позволяет ограничить область прослушивания.

import { SorgeNode, SorgeHandlerMount, SorgeHandlerUpdate, SorgeHandlerUnmount } from 'react-sorge';

const handlerMount: SorgeHandlerMount = (fiber, parentFiber) => {};
const handlerUpdate: SorgeHandlerUpdate = (nextFiber, prevFiber) => {};
const handlerUnmount: SorgeHandlerUnmount = (nextFiber, prevFiber) => {};

<SorgeNode onMount={handlerMount} onUpdate={handlerUpdate} onUnmount={handlerUnmount}>
  <TrackingComponents />
</SorgeNode>;

События

Их можно разделить на 2 группы: для всех типов WorkTag и отдельно для HostRoot.

Каждое вызывается со своим набором агументов:

type mount = (fiber: Fiber, parentFiber: Fiber | null) => void;
type update = (nextFiber: Fiber, prevFiber: Fiber, parentFiber: Fiber | null) => void;
type unmount = (fiber: Fiber) => void;

// tag === WorkTagMap.HostRoot
type mountRoot = (fiber: Fiber) => void;
type updateRoot = (nextFiber: Fiber, prevFiber: Fiber) => void;
type unmountRoot = (fiber: Fiber) => void;

Дополнительные возможности

Для упрощение работы с объектом fiber доступны хелперы. Подключить их можно так:

import {
  findAmongChildren,
  findAmongParents,
  findAssociatedNode,
  getDisplayName,
  getWorkTagMap,
} from 'react-sorge/lib';

findAmongChildren

Поиск среди потомков fiber ноды. Принимает fiber ноду, и функцию checking, в которую передаются потомки для проверки.
Если checking вернёт true, то findAmongChildren вернёт соответствующую fiber ноду.

type findAmongChildren = (fiber: Fiber, checking: (fiberChild: Fiber) => boolean) => Fiber | null;

findAmongParents

Работает как findAmongChildren, только поднимаясь вверх.

type findAmongChildren = (fiber: Fiber, checking: (fiberParent: Fiber) => boolean) => Fiber | null;

findAssociatedNode

Поиск ассоциированного с компонентом html-элемента.
Ищёт первый элемент типа Node внутри компонента.

type findAssociatedNode = (fiber: Fiber) => Node | null;

getDisplayName

Возвращает имя компонента, если сможет определить.

type getDisplayName = (fiber: Fiber) => string | null;

getWorkTagMap

Возвращает карту существующих типов fiber ноды. Среди типов есть ClassComponent, FunctionComponent, ContextConsumer, ContextProvider, HostComponent и другие (всего ~24).

type getWorkTagMap = (version?: string) => WorkTagMap;

Доступные типы

import {
  Fiber,
  WorkTagMap,
  SorgeHandlerMount,
  SorgeHandlerUpdate,
  SorgeHandlerUnmount,
  SorgeHandlerMountRoot,
  SorgeHandlerUpdateRoot,
  SorgeHandlerUnmountRoot
} from 'react-sorge';