你好,我在下一个js项目中使用switch语句来为页面提供特定的组件。switch语句接收一个有效负载,它循环通过这个有效负载,以导出要提供的组件。这些组件已动态导入,现在我希望使用此动态导入和Intersection Observer在组件进入视口时加载组件,以减少初始页面加载时间并进行拆分我已经加入了一个钩子,它使用交集观察器沿着ref来尝试复制我的想法。现在,当我给予一个div引用时,它会观察到组件进入视口,但是当我给我的div添加多个ref时,我仍然只得到一个div与ref一起被观察。
我做错了什么?我以为你可以多次引用同一个ref,然后只使用.current来标识被观察的当前元素?
Switch陈述式:
import React from 'react';
import getTCTEnv from '../../../lib/helpers/get-tct-env';
import IconWishlistButton from '../../wishlist/add-to-wishlist-button/button-types/icon-wishlist-button';
import loadable from '@loadable/component';
import { useOnScreen } from '../../../hooks/on-screen';
const PriorityCollection = loadable(
() => import('@culture-trip/tile-ui-module/dist/collectionRail/PriorityCollections'),
{
resolveComponent: (components) => components.PriorityCollection
}
);
const TravelWithUs = loadable(
() => import('../../../components/trips/travel-with-us/travel-with-us'),
{
resolveComponent: (components) => components.TravelWithUs
}
);
const TrustMessaging = loadable(() => import('../../../components/trips/trust-messaging/index'), {
resolveComponent: (components) => components.TrustMessaging
});
const PressMessaging = loadable(() => import('../../../components/trips/press-messaging'), {
resolveComponent: (components) => components.PressMessaging
});
const TripsChatBanner = loadable(
() => import('../../../components/trips/chat-banner/chat-banner'),
{
resolveComponent: (components) => components.TripsChatBanner
}
);
const HpFeaturedArticles = loadable(
() => import('../home-page-featured-articles/home-page-featured-articles'),
{
resolveComponent: (components) => components.HpFeaturedArticles
}
);
const InstagramSection = loadable(() => import('../../../components/trips/instagram'), {
resolveComponent: (components) => components.InstagramSection
});
const EmailForm = loadable(() => import('../../../components/trips/email-form'));
const ReviewsSection = loadable(() => import('../../../components/trips/reviews'));
export const IncludeComponent = ({ collections, reviewData, type }) => {
const [containerRef, isVisible] = useOnScreen({
root: null,
rootMargin: '0px',
threshold: 0.1
});
const instagramCollection = collections.filter((collection) => collection.type === 'instagram');
const getComponents = () =>
collections.map((el, i) => {
switch (el.type) {
case 'trips':
case 'article':
return (
<PriorityCollection
key={i}
collections={[el]}
tctEnv={getTCTEnv()}
wishlistButton={<IconWishlistButton />}
/>
);
case 'reviews':
return (
<>
<div ref={containerRef} id={i}></div>
<ReviewsSection reviewData={reviewData} />
</>
);
case 'instagram':
return (
<>
<div ref={containerRef} id={i}></div>
<InstagramSection collection={instagramCollection} />
</>
);
case 'featured':
return <PressMessaging />;
case 'trust':
return <TrustMessaging type={type} />;
case 'featuredArticle':
return <HpFeaturedArticles />;
case 'email':
return <EmailForm />;
case 'chat':
return <TripsChatBanner />;
case 'travel':
return <TravelWithUs type={type} />;
default:
return;
}
});
return getComponents();
};
自定义挂钩:
import { useEffect, useState, useRef } from 'react';
export const useOnScreen = (options): any => {
const containerRef = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState([]);
const callbackFunction = (entries) => {
const [entry] = entries;
if (entry.isIntersecting)
setIsVisible((oldArray) => [
...oldArray,
isVisible.indexOf(entry.target.id) === -1 && entry.target.id !== undefined
? entry.target.id
: console.log('nothing')
]);
};
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, options);
if (containerRef.current) observer.observe(containerRef.current);
return () => {
if (containerRef.current) observer.unobserve(containerRef.current);
};
}, [containerRef.current, options]);
return [containerRef, isVisible];
};
目前只有instagram引用被观察到
2条答案
按热度按时间rqmkfv5c1#
如果我对代码的理解是正确的,那么
getComponents
可能会呈现多个组件。你希望两个div都能被观察到,但这并不奏效,因为ref本身并不会触发效果。ref只是一个类似
{ current: null }
的对象。当树被渲染时,containerRef.current
被设置为第一个div,然后它被设置为第二个div,然后效果运行。要执行您想要的操作,您可以:
1.多次调用自定义钩子,并为每个div分配一个
containerRef
。当然,这里的问题是,您也将有多个IntersectionObserver
示例。1.声明多个引用并通过参数将它们传递给自定义挂接,而不是从自定义挂接返回引用。
1.实现一个callback ref,它将每个div添加到列表中,跳过重复项。这个方法允许你在
getComponents
中保持相同的实现,但也是钩子最棘手的地方。8cdiaqws2#
解决方法:
钩子: