🔥

Тред (@belov)


⚛️ Is React Suspense Ready Yet? Тред о том, чему можно поучиться у инженеров «FB», что закладывали Suspense-логику в реконсилер. Ну... помимо того, что код можно ещё и релизить.

Disclaimer: Подчеркну, что тред — исследование внутреннего устройства и попытки понять решения инженеров. Призыва к использованию здесь нет.

Вообще, первое впечатление о Suspense, достаточно обескураживающее. - Во-первых, ты думаешь, что это компонент. - Во-вторых, ты понимаешь, что этот «сахар» не особо-то впечатляет:
notion image

Но если всё же начать разбираться и понять, что «Suspense» — термин, а затем разложить его на составляющие, то их будет всего две: React.lazy() - отвечает за разбиение кода Кэш - отвечает за кэширование данных от API

C Reat.lazy() все знакомы — компонент для код-сплиттинга.
notion image

И для того, чтобы заменять fallback-компонент, на тот, что загружается, тут используется «алгебраический эффект». Объяснение в 5 строк внизу на картинке, а солидная статья по этой ссылке: overreacted.io/algebraic-effe…
notion image

Со вторым компонентом Suspens'а (кэшем) всё неопределённо. С ним непонятно что делать. Уже второй год. В документации так и написано: reactjs.org/docs/concurren…
notion image

Принцип работы React-компонента с кэшем аналогичен — бросить из компонента асинхронную функцию к API, так как для неё уже инкапсулирован обработчик в <Suspense />.
notion image

В этот момент происходит первая фаза понимания паттерна — отрицание. — «Всмысле, кидать промис из компонента?»
notion image

Затем, «гнев». — «Так мне ещё и кэш самому надо инвалидировать? А давно это надо делать на фронте?»
notion image

Потом, торгуешься, но всё же делаешь первую реализацию своего нерабочего кэша (на картинке). — А что, пускай отдыхает 😎 Потом, погружаешься в тему и узнаешь про LRU-алгоритм, так как объект — так-себе кэш. ru.bmstu.wiki/LRU_(Least_Rec…
notion image

В конце приходит и понимание того, что в Suspense, так-то, содержится конструкция catch, которая ожидает выбрасывания промиса от API... ...но ты использовал этот потенциал только для React.lazy() 😶

О да, и вот, без лишних предисловий, 20 твитов спустя, мы у чего-то интересного. 👏

Понятие Suspense не ограничивается только отложенной загрузкой компонентов и данных. Рассмотрим нестабильный компонент <SuspenseList />, что способен делать композицию из <Suspense />. В документации всего 1 абзац. Зато в репозитории есть тесты. Их и почитаем.

Про параметр revealOrder можно узнать самостоятельно. Из одноабзацевой документации. Сейчас же, мы приглядимся что Энрю Кларк покрыл тестами для пропа tail.

Опция tail имеет 2 состояния. Нам интересен tail="collapsed", что использует алгоритм отображения компонентов строго очереди, а не по готовности.
notion image

Десонмтрация работы алгоритма: suspensive-react.artbelov.now.sh/74 листайте вправо.

Продублирую работу алгоритма... Дано: 4 компонента, обёрнутые в SuspenseList c tail="collapsed". Hint: Начните следить за судьбой компонента <D /> 👀
notion image

1 коммит: 3 фоллбэк-компонента из 4. Где <D />? 😒
notion image

2 и 3 коммит — поочерёдная вставка загрузившихся компонентов <A /> и <B />. 4 коммит — одновременная вставка загрузившихся компонентов <C /> и <D />. (О, повезло-повезло...) а вот фоллбэк-компонента <D /> так никто и не видел. 👀
notion image

Реконсилер в реакте штука сложная и она знает цену коммита в (Virtual)DOM. Это дорого. А конкретно в данном случае, было заранее просчитано, что рендерить фоллбэк-компонент - нецелесообразно.

Фактически — реконсилер сэкономил на рендере фоллбэк-компонента, а к следующей транзакции уже был готов и сам загружаемый компонент.

Итого, Suspense своей реализацией показывает: DX — это важно. Кэш — это то, с чем уже пора учиться работать. Для больших транзакций, рациональнее считать время планируемых работ, нежели выполнять инструкции. Ибо если всё важно... то может ничего не важно?