Как выполнить функцию перед монтированием компонента с помощью useEffect?
Хуки
Строго «перед монтированием» useEffect выполнить код не может — эффекты запускаются после коммита. Но у задачи есть корректные решения — зависит от того, что на самом деле нужно.
Почему useEffect «до монтирования» невозможен
Порядок: рендер → коммит в DOM → (useLayoutEffect) → отрисовка → useEffect. Любой эффект видит уже смонтированный компонент. Аналог componentWillMount из классов признан небезопасным (переименован в UNSAFE_componentWillMount и объявлен устаревшим) — код «до монтирования» ломался при конкурентном рендеринге.
Что выбрать под реальную задачу
Инициализация значений — прямо в рендере или в инициализаторах:
const [config, setConfig] = useState(() => buildConfig()); // один раз, ДО первого рендера JSX
const idRef = useRef(generateId()); // тоже до монтированияТело компонента и ленивые инициализаторы выполняются до появления DOM — для чистых вычислений это и есть «перед монтированием».
Успеть до отрисовки кадра — useLayoutEffect:
useLayoutEffect(() => {
const rect = ref.current.getBoundingClientRect(); // DOM уже есть,
setPosition(calc(rect)); // но кадр ещё не показан
}, []);Компонент смонтирован, но пользователь ничего не видел — «до монтирования» с точки зрения глаз.
Данные до появления компонента — выше по дереву: лоадеры маршрута (React Router/Next.js), родитель, который не рендерит ребёнка до готовности ({data && <Child data={data} />}), Suspense.
Чего не делать: запускать побочную логику в теле компонента («один раз» через флаг вне компонента) — нарушение чистоты рендера, ломается в StrictMode.
Коротко для собеседования
useEffect до монтирования не выполняется в принципе (эффекты — после коммита). Чистую инициализацию делают в ленивом useState/useRef (выполняются до рендера JSX), «до показа кадра» — useLayoutEffect, данные заранее — лоадеры маршрутов/родитель/Suspense. Побочный код в теле компонента — антипаттерн.