Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 在react.js中加载DOM时回调_Reactjs - Fatal编程技术网

Reactjs 在react.js中加载DOM时回调

Reactjs 在react.js中加载DOM时回调,reactjs,Reactjs,我希望在react.js组件的DOM元素(包括所有子节点)实际加载到页面并准备就绪时,在该组件上调用回调。具体来说,我有两个组件,我想渲染相同的大小,选择具有较大自然大小的组件的最大值 看起来componentDidMount并不是我真正想要的,因为每个组件只调用一次,但我希望在组件完成渲染时再次调用回调。我想我可以向顶级DOM元素添加一个onLoad事件,但我想这只适用于某些元素,比如和看起来像是componentDidMount和componentdiddupdate的组合将完成任务。第一个

我希望在react.js组件的DOM元素(包括所有子节点)实际加载到页面并准备就绪时,在该组件上调用回调。具体来说,我有两个组件,我想渲染相同的大小,选择具有较大自然大小的组件的最大值


看起来
componentDidMount
并不是我真正想要的,因为每个组件只调用一次,但我希望在组件完成渲染时再次调用回调。我想我可以向顶级DOM元素添加一个
onLoad
事件,但我想这只适用于某些元素,比如

看起来像是
componentDidMount
componentdiddupdate
的组合将完成任务。第一个在初始渲染之后调用,当DOM可用时,第二个在任何后续渲染之后调用,一旦更新的DOM可用。在我的例子中,我让它们都委托给一个公共函数来做同样的事情。

我将componentDidUpdate应用到表中,使所有列具有相同的高度。它的工作原理与jquery中的$(window.load()相同

例如:


在componentDidMount中添加onload侦听器

class Comp1 extends React.Component {
 constructor(props) {
    super(props);
    this.handleLoad = this.handleLoad.bind(this);
 }

 componentDidMount() {
    window.addEventListener('load', this.handleLoad);
 }

 componentWillUnmount() { 
   window.removeEventListener('load', this.handleLoad)  
 }

 handleLoad() {
  $("myclass") //  $ is available here
 }
}

在现代浏览器中,它应该是

try() {
     if (!$("#element").size()) {
       window.requestAnimationFrame(try);
     } else {
       // do your stuff
     }
};

componentDidMount(){
     this.try();
}

我发现,只需将
componentDidMount
componentdiddupdate
中的代码包装为
setTimeout
,时间为0毫秒,即可确保在执行
setTimeout
功能之前,浏览器DOM已随React更改而更新

像这样:

componentDidMount() {
    setTimeout(() => {
        $("myclass") //  $ is available here
    }, 0)
}

这会将匿名函数放在JS事件队列中,以便在当前运行的React stack框架完成后立即运行。

下面是我在尝试使用document.getElementsByClassName获取类之前,在DOM准备就绪时要等待的结果。我从componentDidMount()生命周期方法调用了这个函数

     changeIcon() {
            if (
                document.getElementsByClassName('YOURCLASSNAME')
                    .length > 0 &&
                document.getElementsByClassName('YOURCLASSNAME').length > 0
            ) {
                document.getElementsByClassName(
                    'YOURCLASSNAME'
                )[0].className = 'YOUR-NEW-CLASSNAME';
                document.getElementsByClassName(
                    'YOUR-OTHER-EXISTING-CLASSNAME'
                )[0].style.display = 'block';
            } else {
                setTimeout(this.changeIcon, 500);
            }
     }

组合使用
componentDidMount
componentdiddupdate
将在带有类组件的代码中完成任务。 但是,如果您在用全部功能组件
编写代码,那么效果挂钩将做得非常好,它与
componentDidMount
componentdiddupdate
是一样的

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
import React,{useState,useffect}来自“React”;
函数示例(){
const[count,setCount]=useState(0);
//与componentDidMount和componentDidUpdate类似:
useffect(()=>{
//使用浏览器API更新文档标题
document.title=`您单击了${count}次`;
});
返回(
您单击了{count}次

设置计数(计数+1)}> 点击我 ); }


您可以使用
useRef
hook查看容器元素。 请注意,您需要特别注意
ref
当前值,否则它将无法工作

例如:

  const containerRef = useRef();
  const { current } = containerRef;

  useEffect(setLinksData, [current]);

return (
    <div ref={containerRef}>
      // your child elements...
    </div>
)
const containerRef=useRef();
const{current}=containerRef;
useffect(setLinksData,[当前]);
返回(
//您的子元素。。。
)

这对我来说似乎很有效

const [isLoaded, setIsLoaded] = useState(false);
const [isPageLoaded, setIsPageLoaded] = useState(false); //this helps

useEffect(() => {
    setIsLoaded(true);
}, []);

useEffect(() => {
    if (isLoaded) {
        setIsPageLoaded(true);
    }
}, [isLoaded]);

不幸的是,
componentdiddupdate
没有为初始渲染调用,因此在道具或状态更改之前不会应用您的函数:呵呵,除了现代浏览器不使用jquery=P之外。不过这是使用动画帧的好技巧,假设它应该是实时更新的。但是componentDidUpdate将被多次调用,而实际上不是feasible@John什么方式不可行?@brianmearns在使用redux这样的状态管理库时,父道具可以多次更改,并且每次调用componentDidUpdate时都会更改。如果我们只需要等待初始DOM渲染,那么在这种情况下是不可行的。在这种情况下,在componentDidMount中附加负载侦听器似乎更好,如下面的一个答案所示。这是否只适用于顶级组件?此方法如何确保所有子组件都已完成渲染?当我使用此方法时,它为我提供了最大深度,因为它创建了一个无限循环。还记得添加remove eventlistener
componentWillUnmount(){window.removeEventListener('load',this.handleLoad)}
我喜欢这个答案的方向,但是你的例子并不能解决这个问题。我认为这个问题与加载事件有关。使用useEffect钩子,您可以检测到用户访问“view/page/…”的时刻,而不是等待所有元素出现在屏幕中。设置超时的点是什么?我理解它在事件队列方面的作用,但为什么您认为这在这里是必要的?根据react文档,在加载/更新DOM元素之前,不会调用这两个方法。通过添加setTimeout,您在后续更新中引入了竞争条件。如果我在componentDidMount中直接调用我的lazyLoadImages函数,则位于浏览器选项卡中的页面加载指示器将一直旋转,直到加载所有图像。但如果wrap lazyLoadImages函数在setTimeout中使用100ms参数,这种情况就不同了。当图像开始在后台加载时,加载指示器将很快停止旋转。设置超时使体验更好。将延迟加载函数绑定到WindowOnLoad事件也会执行相同的操作,但它不适用于SPA。
const [isLoaded, setIsLoaded] = useState(false);
const [isPageLoaded, setIsPageLoaded] = useState(false); //this helps

useEffect(() => {
    setIsLoaded(true);
}, []);

useEffect(() => {
    if (isLoaded) {
        setIsPageLoaded(true);
    }
}, [isLoaded]);