我本以为useEffect的第一个函数在第一个渲染之前被调用,但是当我调用下面的方法时,恰好在return方法调用被调用之前,我的console.log被调用,然后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.log('useEffect before setInView')
setInView(isInView());
console.log('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.log('just before render return')
return (
<img
ref={imageRef}
src={inView ? secondaryImg : primaryImg}
alt="image here"
/>
);
};
export default ImageToggleOnMouseOver;
答案 0 :(得分:2)
使用useEffect
创建的效果在渲染提交阶段之后运行,因此在渲染周期之后运行。这是为了确保在渲染提交阶段不会执行任何可能导致不一致的副作用
根据文档
突变,订阅,计时器,日志记录和其他副作用是 不允许在功能组件的主体内部(指 作为React的渲染阶段)。这样做会导致混淆的错误和 用户界面中的不一致。
传递给
useEffect
的函数将运行 将渲染提交到屏幕后。
useEffect
挂钩可用于为类组件复制componentDidMount
,componentDidUpdate
和componentWillUnmount
生命周期方法的行为,具体取决于传递给依赖项数组的参数,即useEffect的第二个参数和回调函数中的返回函数,该函数在运行下一个效果之前或在卸载之前执行
对于某些用途,例如animations
,您可以使用useLayoutEffect
,它在所有DOM突变后都同步执行。使用它从DOM读取布局并同步重新渲染。在浏览器有机会绘制之前,useLayoutEffect内部安排的更新将被同步刷新。
答案 1 :(得分:1)
根据useEffect
documentation:
如果您熟悉React类的生命周期方法,则可以将useEffect Hook视为componentDidMount,componentDidUpdate和componentWillUnmount的组合。
是的,它在第一个渲染和每个后续渲染之后运行。