渲染是否在 React Hooks useEffect 中的函数被调用之前发生? [英] Does a render happen before function in React Hooks useEffect is called?

查看:131
本文介绍了渲染是否在 React Hooks useEffect 中的函数被调用之前发生?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我本以为 useEffect 的第一个函数会在第一次渲染之前被调用,但是当我调用下面的方法时,我的 console.log 就在 return 方法调用被调用之前,然后 useEffect 的第一个参数函数被调用.

I would have thought that useEffect's first function gets called before the first render, but when I call the method below, my console.log just before the return method call gets called, then the useEffect's first parameter function gets called.

调用顺序:

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 创建的效果在渲染提交阶段之后运行,因此在渲染周期之后运行.这是为了确保在渲染提交阶段不会执行可能导致不一致的副作用

Effects created using useEffect are run after the render commit phase and hence after the render cycle. This is to make sure that no side-effects are executed during the render commit phase which might cause inconsistency

根据文档

突变、订阅、计时器、日志记录和其他副作用是不允许在功能组件的主体内部(称为作为 React 的渲染阶段).这样做会导致令人困惑的错误和用户界面不一致.

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.

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

The function passed to useEffect will run after the render is committed to the screen.

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

useEffect hook can be used to replicate behavior of componentDidMount, componentDidUpdate, and componentWillUnmount lifecycle methods for class components depending the arguments passed to the dependency array which is the second argument to useEffect and the return function from within the callback which is executed before the next effect is run or before unmount

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

For certain useCases such as animations you may make use of useLayoutEffect which is executed synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.

这篇关于渲染是否在 React Hooks useEffect 中的函数被调用之前发生?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆