当前位置: 首页 > 面试题库 >

是否在调用React Hooks useEffect中的函数之前进行渲染?

宰烈
2023-03-14
问题内容

我以为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;

问题答案:

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

根据文档

不允许在功能组件的主体内部进行突变,订阅,计时器,日志记录和其他副作用(称为React的渲染阶段)。这样做会导致UI中的错误和不一致。

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

useEffect挂钩可用于复制类组件的,和生命周期方法的行为componentDidMount,具体取决于传递给依赖项数组的参数(这是useEffect的第二个参数)以及在执行下一个效果之前或之前在回调中执行的返回函数卸下componentDidUpdate``componentWillUnmount

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



 类似资料:
  • 问题内容: 假设我有一个Base类,该类具有一个带有TextBox对象作为参数的单个参数构造函数。如果我有以下形式的简单类: 我会收到一条错误消息,告诉我对super的调用必须是构造函数中的第一个调用。但是,奇怪的是,我可以做到这一点。 为什么允许这样做,但第一个例子不允许?我可以理解需要先设置子类,并且可能不允许在调用超级构造函数之前实例化对象变量。但是t显然是方法(局部)变量,那么为什么不允许

  • 如何在组件返回中使用promise函数,如下所示: 因此,结果将是: 即使我在同一个组件中有几个promise,我也必须使用?

  • 在使用useState和useReducer钩子时,我意识到一个问题,即更新状态函数(setState,dispatch)之后的任何代码行都将在下一次重新呈现时被调用(更新之前的状态)。这意味着更新状态函数会导致立即重新渲染,而不是等待整个函数执行。 上述代码将按以下顺序记录: 步骤0 组件正在重新渲染... true 步骤1 步骤2真 有人给我解释更新状态挂钩的工作流程吗?先谢谢你。

  • 我的问题是:为什么调用不更快或更好,从而更可取?

  • 在我的应用程序中,我以以下方式加载缓存。 加载用户缓存loadUserCache() 加载帐户缓存loadAccountCache() 加载客户缓存loadCustomerCache() 上述每个调用都涉及一个数据库调用。像怀斯一样,有6-7个电话。 当我的应用程序加载时,我必须等待缓存加载。 那些都是一个接一个的顺序调用。 如果我能找到一种方法并行地进行这些调用,那么应用程序加载期间的等待时间将

  • #include <stdio.h> int func(void) { return 3; } int main(void) { int a = 0; a = func(); printf("%d\n", a); return 0; } 技巧 使用gdb调试遇到函数时,使用step命令(缩写为s)可以进入函数(函数必须有调试信息)。以上面代码为例: