Skip to content

Commit

Permalink
feat: add ignoreZeroMeasurement prop to LazyChild
Browse files Browse the repository at this point in the history
  • Loading branch information
johnhaup committed Jun 2, 2024
1 parent 6b756d2 commit 90b458b
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ export function CoolComponentC() {
}
};

// Fired when LazyChild has 75% visibility
const onPercentVisibleThresholdPass = async () => {
analyticsCall();
};

if (!data) {
// Trigger has fired and no data :(
return null;
}

Expand All @@ -89,14 +91,15 @@ export function CoolComponentC() {
**LazyScrollView**
| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| offset | `number` | Yes | 0 (bottom of ScrollView) | How far above or below the bottom of the `ScrollView` the threshold trigger is. Negative is above, positive it below.
| `offset` | `number` | Yes | 0 (bottom of `LazyScrollView`) | How far above or below the bottom of the `LazyScrollView` the threshold trigger is. Negative is above, positive it below.

**LazyChild**
| Prop | Type | Optional | Default | Description |
| --- | --- | --- | --- | --- |
| onThresholdPass | `function` | No | - | Callback that will fire when top of `View` passes threshold trigger.
| percentVisibleThreshold | `number` (Unit Interval) | Yes | - | Percentage of LazyChild that will trigger `onPercentVisibleThresholdPass`.
| onPercentVisibleThresholdPass | `function` | Yes | - | Callback that will fire when `percentVisibleThreshold` is visible above bottom of LazyScrollView.
| `onThresholdPass` | `function` | **No** | - | Callback that will fire when top of `View` passes threshold trigger.
| `percentVisibleThreshold` | `number` (Unit Interval) | Yes | 1 | Percentage of LazyChild that will trigger `onPercentVisibleThresholdPass`.
| `onPercentVisibleThresholdPass` | `function` | Yes | - | Callback that will fire when `percentVisibleThreshold` is visible above bottom of LazyScrollView. Note that this trigger is tied to the bottom of the LazyScrollView, not the threshold.
| `ignoreZeroMeasurement` | `boolean` | Yes | `true` | Protects against firing callback on measurement with zero value. Good to set to false if you know the LazyChild is the first item in the LazyScrollview.

## Example

Expand Down
16 changes: 16 additions & 0 deletions src/components/LazyChild.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import Animated, {
runOnJS,
useAnimatedReaction,
useAnimatedRef,
useDerivedValue,
useSharedValue,
} from 'react-native-reanimated';
import { useAnimatedContext } from '../context/AnimatedContext';
import { Platform } from 'react-native';

interface Props {
children: React.ReactNode;
Expand All @@ -22,6 +24,10 @@ interface Props {
* Callback to fire when the LazyChild's viewable area exceeds the percentVisibleThreshold.
*/
onPercentVisibleThresholdPass?: () => void;
/**
* Protects against firing callback on measurement with zero value. Default is true. Good to set to false if you know the LazyChild is the first item in the LazyScrollview.
*/
ignoreZeroMeasurement?: boolean;
}

/**
Expand All @@ -32,12 +38,14 @@ export function LazyChild({
onThresholdPass,
percentVisibleThreshold = 1,
onPercentVisibleThresholdPass,
ignoreZeroMeasurement = true,
}: Props) {
const { triggerValue, hasReachedEnd, scrollValue, bottomYValue } =
useAnimatedContext();

const _viewRef = useAnimatedRef<Animated.View>();
const _hasFiredScrollViewThresholdTrigger = useSharedValue(false);
const _ignoreZeroMeasurement = useSharedValue(ignoreZeroMeasurement);
const _isAndroid = useSharedValue(Platform.OS === 'android');
const _canMeasure = useDerivedValue(
// https://github.com/software-mansion/react-native-reanimated/issues/5006#issuecomment-1826495797
Expand Down Expand Up @@ -70,6 +78,10 @@ export function LazyChild({

// Track scollValue to make reaction fire
if (measurement !== null && scrollValue.value > -1) {
if (_ignoreZeroMeasurement.value && measurement.pageY === 0) {
return false;
}

return (
measurement.pageY < triggerValue.value &&
!_hasFiredScrollViewThresholdTrigger.value
Expand Down Expand Up @@ -123,6 +135,10 @@ export function LazyChild({

// Track scollValue to make reaction fire
if (measurement !== null && scrollValue.value > -1) {
if (_ignoreZeroMeasurement.value && measurement.pageY === 0) {
return false;
}

const percentOffset = measurement.height * _percentVisibleTrigger.value;
const percentTrigger = bottomYValue.value - percentOffset;

Expand Down

0 comments on commit 90b458b

Please sign in to comment.