繁体   English   中英

ReactJS如何仅在向下滚动并到达页面时才呈现组件?

[英]ReactJS how to render a component only when scroll down and reach it on the page?

我有一个反应组件Data ,其中包括几个图表组件; BarChart LineChart ...等。

Data组件开始渲染时,需要一段时间才能从 API 接收到每个图表所需的数据,然后它开始响应并渲染所有图表组件。

我需要的是,当我向下滚动并到达页面时才开始呈现每个图表。

有什么办法可以帮助我实现这一目标吗?

您至少有三个选项可以做到这一点:

  1. 跟踪组件是否在视口中(对用户可见)。 然后渲染它。 你可以使用这个 HOC https://github.com/roderickhsiao/react-in-viewport

  2. 使用https://react-fns.netlify.com/docs/en/api.html#scroll明确跟踪“y”滚动位置

  3. 使用 Intersection Observer API https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API编写您自己的 HOC

要渲染组件,您可能需要另一个 HOC,它会根据它收到的 props 返回 Chart 组件或“null”。

我尝试了很多库,但找不到最适合我需要的东西,所以我为此编写了一个自定义钩子,希望对您有所帮助

import { useState, useEffect } from "react";

const OPTIONS = {
  root: null,
  rootMargin: "0px 0px 0px 0px",
  threshold: 0,
};

const useIsVisible = (elementRef) => {
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    if (elementRef.current) {
      const observer = new IntersectionObserver((entries, observer) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setIsVisible(true);
            observer.unobserve(elementRef.current);
          }
        });
      }, OPTIONS);
      observer.observe(elementRef.current);
    }
  }, [elementRef]);

  return isVisible;
};

export default useIsVisible;

然后你可以使用钩子如下:

import React, { useState, useEffect, useRef } from "react";
import useVisible from "../../hooks/useIsVisible";

function Deals() {
  const elemRef = useRef();
  const isVisible = useVisible(elemRef);
  return (
    <div ref={elemRef}>hello {isVisible && console.log("visible")}</div>
)}

您可以检查窗口滚动位置,如果滚动位置靠近您的 div - 显示它。 为此,您可以使用简单的反应渲染条件。

import React, {Component} from 'react';
import PropTypes from 'prop-types';

class MyComponent extends Component {
constructor(props){
    super(props);

    this.state = {
        elementToScroll1: false,
        elementToScroll2: false,
    }

    this.firstElement = React.createRef();
    this.secondElement = React.createRef();
}
componentDidMount() {
    window.addEventListener('scroll', this.handleScroll);
}

componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll);
}
handleScroll(e){
    //check if scroll position is near to your elements and set state {elementToScroll1: true}
    //check if scroll position is under to your elements and set state {elementToScroll1: false}
}
render() {
    return (
        <div>
            <div ref={this.firstElement} className={`elementToScroll1`}>
                {this.state.elementToScroll1 && <div>First element</div>}
            </div>
            <div ref={this.secondElement} className={`elementToScroll2`}>
                {this.state.elementToScroll2 && <div>Second element</div>}
            </div>
        </div>
    );
}
}

MyComponent.propTypes = {};

export default MyComponent;

这可能对您有所帮助,这只是一个快速的解决方案。 它会为您生成一些重新渲染操作,因此请注意。

我认为在 React 中最简单的方法是使用react-intersection-observer

例子:

import { useInView } from 'react-intersection-observer';

const Component = () => {
  const { ref, inView, entry } = useInView({
    /* Optional options */
    threshold: 0,
  });

  useEffect(()=>{
      //do something here when inView is true
  }, [inView])

  return (
    <div ref={ref}>
      <h2>{`Header inside viewport ${inView}.`}</h2>
     </div>
  );
};

我还建议在选项对象中使用triggerOnce: true ,这样效果只会在用户第一次滚动到它时发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM