渲染是否在 React Hooks useEffect 中的函数被调用之前发生?

IT技术 reactjs react-hooks
2021-04-11 09:42:57

我原以为 useEffect 的第一个函数会在第一次渲染之前被调用,但是当我调用下面的方法时,我的 console.log 就在 return 方法调用被调用之前,然后 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;
2个回答

使用创建的效果在useEffect渲染提交阶段之后运行,因此在渲染周期之后运行。这是为了确保在渲染提交阶段不会执行可能导致不一致的副作用

根据文档

函数组件的主体(称为 React 的渲染阶段)内部不允许发生突变、订阅、计时器、日志记录和其他副作用。这样做会导致 UI 中出现令人困惑的错误和不一致。

传递给的函数useEffect将在渲染提交到屏幕后运行。

useEffecthook 可用于复制类组件的、 和生命周期方法的行为componentDidMount具体取决于传递给依赖数组的参数,这是 useEffect 的第二个参数和回调中的返回函数,该回调在下一个效果运行之前或之前执行卸载componentDidUpdatecomponentWillUnmount

对于某些用例,例如animations您可能会useLayoutEffect在所有 DOM 突变后同步执行。使用它从 DOM 读取布局并同步重新渲染。在浏览器有机会绘制之前, useLayoutEffect 内计划的更新将同步刷新。

谢谢@Shubham,正如你所说,对于“某些情况”。我的情况不是其中之一。
2021-06-18 09:42:57

根据useEffect 文档

如果您熟悉 React 类的生命周期方法,您可以将 useEffect Hook 视为 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。

所以是的,它在第一次渲染和每个后续渲染之后运行。