reactjs 观察可见性的高阶分量:React?

myss37ts  于 2023-01-04  发布在  React
关注(0)|答案(2)|浏览(146)

我已经创建了一个高阶组件,如下所示:

import React from 'react';

interface IVisibility {
    Component: JSX.Element;
    visibilityThreshold?: number;
    onVisibleCallback?: () => void;
}

const VisibilityHandler = ({
    Component,
    visibilityThreshold,
    onVisibleCallback
}: IVisibility) => {
    const ref = React.useRef(null);
    React.useEffect(() => {
        const componentObserver = new IntersectionObserver(
            (entries) => {
                const [entry] = entries;
                if (entry.isIntersecting) {
                    onVisibleCallback ? onVisibleCallback() : null;
                }
            },
            {
                rootMargin: '0px',
                threshold: visibilityThreshold ?? 0
            }
        );
        const current = ref.current;

        if (current) componentObserver.observe(current);

        return () => {
            componentObserver.disconnect();
        };
    }, [visibilityThreshold, onVisibleCallback]);

    return <section ref={ref}>{Component}</section>;
};

export default VisibilityHandler;

并像这样使用它:

<VisibilityHandler Component={<div>Hello World</div>} />

然而,这将每个组件 Package 到一个节中,这是我不想要的。我尝试使用React.Fragment,但它不允许您传递ref来跟踪组件。有没有更好的方法来重新创建此HOC,以便在不将其 Package 到额外的div或section中的情况下合并可见性跟踪?

u59ebvdq

u59ebvdq1#

您可以使用

  • 作为一个孩子
  • React.cloneElement

作为孩子的功能

<VisibilityHandler Component={({ ref }) => <div ref={ref}>Hello world</div>} />

你必须更改你的HOC代码

- return <section ref={ref}>{Component}</section>;
 + return Component({ ref });

React.cloneElement
文件
你的案子

- return <section ref={ref}>{Component}</section>;
 + return React.cloneElement(Component, { ref });
rsaldnfx

rsaldnfx2#

我发现了一个非常简洁的方法,就像这样:

import React from 'react';

interface IVisibility {
    Component: JSX.Element;
    visibilityThreshold?: number;
    onVisibleCallback?: () => void;
}

const VisibilityHandler = ({
    Component,
    visibilityThreshold,
    onVisibleCallback
}: IVisibility): JSX.Element => {
    const ref = React.useRef(null);
    React.useEffect(() => {
        const componentObserver = new IntersectionObserver(
            (entries) => {
                const [entry] = entries;
                if (entry.isIntersecting) {
                    onVisibleCallback ? onVisibleCallback() : null;
                }
            },
            {
                rootMargin: '0px',
                threshold: visibilityThreshold ?? 0
            }
        );
        const current = ref.current;

        if (current) componentObserver.observe(current);

        return () => {
            componentObserver.disconnect();
        };
    }, [visibilityThreshold, onVisibleCallback]);

    return <Component.type {...Component.props} ref={ref} />;
};

export default VisibilityHandler;

相关问题