diff --git a/src/__tests__/hooks.test.tsx b/src/__tests__/hooks.test.tsx index fb90d29e..23e7556d 100644 --- a/src/__tests__/hooks.test.tsx +++ b/src/__tests__/hooks.test.tsx @@ -1,5 +1,5 @@ import React, { useCallback } from 'react'; -import { render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { useInView } from '../useInView'; import { intersectionMockInstance, mockAllIsIntersecting } from '../test-utils'; import { IntersectionOptions } from '../index'; @@ -257,3 +257,25 @@ test('should handle multiple hooks on the same element', () => { expect(getByTestId('item-2').getAttribute('data-inview')).toBe('true'); expect(getByTestId('item-3').getAttribute('data-inview')).toBe('true'); }); + +test('should handle thresholds missing on observer instance', () => { + render(); + const wrapper = screen.getByTestId('wrapper'); + const instance = intersectionMockInstance(wrapper); + // @ts-ignore + instance.thresholds = undefined; + mockAllIsIntersecting(true); + + screen.getByText('true'); +}); + +test('should handle thresholds missing on observer instance with no threshold set', () => { + render(); + const wrapper = screen.getByTestId('wrapper'); + const instance = intersectionMockInstance(wrapper); + // @ts-ignore + instance.thresholds = undefined; + mockAllIsIntersecting(true); + + screen.getByText('true'); +}); diff --git a/src/observers.ts b/src/observers.ts index c70cb4c1..32278132 100644 --- a/src/observers.ts +++ b/src/observers.ts @@ -50,6 +50,7 @@ function createObserver(options: IntersectionObserverInit) { if (!instance) { // Create a map of elements this observer is going to observe. Each element has a list of callbacks that should be triggered, once it comes into view. const elements = new Map>(); + let thresholds: number[] | readonly number[]; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { @@ -57,9 +58,7 @@ function createObserver(options: IntersectionObserverInit) { // -Firefox ignores `threshold` when considering `isIntersecting`, so it will never be false again if `threshold` is > 0 const inView = entry.isIntersecting && - (observer.thresholds ?? [0]).some( - (threshold) => entry.intersectionRatio >= threshold, - ); + thresholds.some((threshold) => entry.intersectionRatio >= threshold); // @ts-ignore support IntersectionObserver v2 if (options.trackVisibility && typeof entry.isVisible === 'undefined') { @@ -74,6 +73,13 @@ function createObserver(options: IntersectionObserverInit) { }); }, options); + // Ensure we have a valid thresholds array. If not, use the threshold from the options + thresholds = + observer.thresholds || + (Array.isArray(options.threshold) + ? options.threshold + : [options.threshold || 0]); + instance = { id, observer,