useInsertionEffect

useInsertionEffect для авторів бібліотек CSS-in-JS. Якщо ви не працюєте над бібліотекою CSS-in-JS і вам потрібне місце для вставки стилів, вам краще використовувати useEffect або useLayoutEffect.

useInsertionEffect дозволяє вставляти елементи у DOM до того, як буде застосовано ефект fire.

useInsertionEffect(setup, dependencies?)

Довдіник

useInsertionEffect(setup, dependencies?)

Виклик useInsertionEffect для вставки стилів перед запуском ефектів, які можуть потребувати читання макета:

import { useInsertionEffect } from 'react';

// Inside your CSS-in-JS library
function useCSS(rule) {
  useInsertionEffect(() => {
    // ... inject <style> tags here ...
  });
  return rule;
}

Дивіться більше прикладів нижче.

Параметри

  • setup: Функція з логікою вашого ефекту. Ваша функція налаштування може також опціонально повертати функцію cleanup. Коли ваш компонент буде додано до DOM, але до запуску ефектів компонування, React запустить вашу функцію налаштування. Після кожного повторного рендерингу зі зміненими залежностями React спочатку запустить функцію очищення (якщо ви її надали) зі старими значеннями, а потім запустить вашу функцію налаштування з новими значеннями. Коли ваш компонент буде видалено з DOM, React запустить вашу функцію очищення.

  • додаткові залежності: список усіх реактивних значень, на які посилаються у коді setup. Реактивні значення включають пропси, стан і всі змінні та функції, оголошені безпосередньо у тілі вашого компонента. Якщо ваш лінтер налаштований на React, він буде перевіряти, щоб кожне реактивне значення було правильно вказане як залежність. Список залежностей повинен мати постійну кількість елементів і бути записаний в рядок як [dep1, dep2, dep3]. React порівняє кожну залежність з її попереднім значенням за допомогою алгоритм порівняння Object.is. Якщо ви не вкажете залежності взагалі, ваш ефект буде перезапускатися після кожного повторного рендерингу компонента.

Повернення

useInsertionEffect повертає undefined.

Застереження

  • Ефекти працюють лише на клієнті. Вони не працюють під час рендерингу на сервері.
  • Неможливо оновити стан зсередини useInsertionEffect.
  • На час виконання useInsertionEffect посилання ще не прикріплено.
  • useInsertionEffect може виконуватися до або після оновлення DOM. Не слід покладатися на те, що DOM буде оновлено у певний момент часу.
  • На відміну від інших типів ефектів, які запускають очищення для кожного ефекту, а потім налаштування для кожного ефекту, useInsertionEffect запускає очищення та налаштування по одному компоненту за раз. Це призведе до "чергування" функцій очищення та налаштування.

Використання

Впровадження динамічних стилів з бібліотек CSS-в-JS

Традиційно, ви б стилізували React-компоненти за допомогою звичайного CSS.

// In your JS file:
<button className="success" />

// In your CSS file:
.success { color: green; }

Деякі команди вважають за краще створювати стилі безпосередньо у коді JavaScript замість написання файлів CSS. Зазвичай це вимагає використання бібліотеки або інструменту CSS-in-JS. Існує три поширених підходи до CSS-in-JS:

  • Статичне видобування в CSS файли за допомогою компілятора
  • Вбудовані стилі, наприклад, <div style={{ opacity: 1 }}>
  • Впровадження тегів <style> під час виконання
  • Якщо ви використовуєте CSS-in-JS, ми рекомендуємо комбінувати перші два підходи (файли CSS для статичних стилів, вбудовані стилі для динамічних стилів). Ми не рекомендуємо вставляти тег <style> під час виконання з двох причин:

    1. Впровадження виконання змушує браузер переобчислювати стилі набагато частіше.
    2. Введення виконання може бути дуже повільним, якщо воно відбувається у невідповідний момент життєвого циклу React.

    Перша проблема не розв'язується, але useInsertionEffect допоможе вам розв'язати другу проблему.

    Виклик useInsertionEffect для вставки стилів до того, як спрацює будь-який ефект компонування:

    // Inside your CSS-in-JS library
    let isInserted = new Set();
    function useCSS(rule) {
      useInsertionEffect(() => {
        // As explained earlier, we don't recommend runtime injection of <style> tags.
        // But if you have to do it, then it's important to do in useInsertionEffect.
        if (!isInserted.has(rule)) {
          isInserted.add(rule);
          document.head.appendChild(getStyleForRule(rule));
        }
      });
      return rule;
    }
    
    function Button() {
      const className = useCSS('...');
      return <div className={className} />;
    }

    Подібно до useEffect, useInsertionEffect не виконується на сервері. Якщо вам потрібно зібрати, які правила CSS були використані на сервері, ви можете зробити це під час рендерингу:

    let collectedRulesSet = new Set();
    
    function useCSS(rule) {
      if (typeof window === 'undefined') {
        collectedRulesSet.add(rule);
      }
      useInsertionEffect(() => {
        // ...
      });
      return rule;
    }

    Детальніше про оновлення бібліотек CSS-in-JS за допомогою ін'єкції під час виконання читайте у useInsertionEffect.

    Чим це краще, ніж застосування стилів під час рендерингу або використання LayoutEffect?

    Якщо ви вставляєте стилі під час рендерингу, а React обробляє неблокуюче оновлення, браузер буде перераховувати стилі кожного кадру під час рендерингу дерева компонентів, що може бути надзвичайно повільно.

    useInsertionEffect краще, ніж вставляти стилі під час useLayoutEffect або useEffect, оскільки це гарантує, що до моменту запуску інших ефектів у ваших компонентах теги <style> вже буде вставлено. Інакше обчислення компонування у звичайних ефектах були б неправильними через застарілі стилі.