Я бы подумал, что первая функция useEffect вызывается до первого рендеринга, но когда я вызываю метод ниже, мой console.info непосредственно перед вызовом метода возврата, тогда вызывается функция первого параметра useEffect.
порядок звонков:
just before render return
ImageToggleOnScroll.js:8 useEffect before setInView
ImageToggleOnScroll.js:10 useEffect after setInView
Источник:
import React, {useState,useRef,useEffect} from "react";
// primaryImg is black and white, secondaryImg is color
const ImageToggleOnMouseOver = ({ primaryImg, secondaryImg }) => {
const imageRef = useRef(null);
useEffect(() => {
console.info('useEffect before setInView')
setInView(isInView());
console.info('useEffect after setInView')
window.addEventListener("scroll", scrollHandler);
return () => {
window.removeEventListener("scroll", scrollHandler);
};
}, []);
const isInView = () => {
if (imageRef.current) {
const rect = imageRef.current.getBoundingClientRect();
return rect.top >= 0 && rect.bottom <= window.innerHeight;
}
return false;
};
const [inView, setInView] = useState(false);
const scrollHandler = () => {
setInView(() => {
return isInView();
});
};
console.info('just before render return')
return (
<img
ref = {imageRef}
src = {inView ? secondaryImg : primaryImg}
alt = "image here"
/>
);
};
export default ImageToggleOnMouseOver;





Согласно useEffectдокументация:
If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
Так что да, он запускается после первого рендера и каждого последующего рендера.
Эффекты, созданные с помощью useEffect, запускаются после фазы фиксации рендеринга и, следовательно, после цикла рендеринга. Это делается для того, чтобы убедиться, что на этапе фиксации рендеринга не выполняются никакие побочные эффекты, которые могут вызвать несогласованность.
Согласно документации
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React’s render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
The function passed to
useEffectwill run after the render is committed to the screen.
useEffect ловушку можно использовать для воспроизведения поведения методов жизненного цикла componentDidMount, componentDidUpdate и componentWillUnmount для компонентов класса в зависимости от аргументов, переданных в массив зависимостей, который является вторым аргументом для useEffect, и функции возврата из обратного вызова, который выполняется перед следующим эффектом. выполняется или перед размонтированием
Для определенных вариантов использования, таких как animations, вы можете использовать useLayoutEffect, который выполняется синхронно после всех мутаций DOM. Используйте это для чтения макета из DOM и синхронного повторного рендеринга. Обновления, запланированные внутри useLayoutEffect, будут сбрасываться синхронно до того, как браузер сможет отрисовать.
Спасибо @Shubham, как вы сказали, за «некоторые случаи». Мой случай не из их числа.