From 83d21dd4ade25f3bb8487bf2f8de3df68633d01a Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 27 Dec 2022 20:57:18 +0000 Subject: [PATCH 1/2] fix(web): invalidate position on ancestor scroll Fixes #471. Added a test case to `example-web`. --- example-web/src/Examples.tsx | 27 ++++++++++++++- package/src/RNCSliderNativeComponent.web.tsx | 36 +++++++++++++++----- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/example-web/src/Examples.tsx b/example-web/src/Examples.tsx index 7a8ed1ce..f42fc890 100644 --- a/example-web/src/Examples.tsx +++ b/example-web/src/Examples.tsx @@ -1,6 +1,6 @@ import React, {useState} from 'react'; // @ts-ignore -import {Text, View, StyleSheet} from 'react-native'; +import {Text, View, StyleSheet, ScrollView} from 'react-native'; // @ts-ignore import Slider, {SliderProps} from '@react-native-community/slider'; @@ -201,4 +201,29 @@ export const examples: Props[] = [ return ; }, }, + { + title: 'Slider in horizontal scroll view', + render() { + return ( + + + + + Scroll right, then slide ➔ + + + + ); + }, + }, ]; diff --git a/package/src/RNCSliderNativeComponent.web.tsx b/package/src/RNCSliderNativeComponent.web.tsx index a454ef51..6867f862 100644 --- a/package/src/RNCSliderNativeComponent.web.tsx +++ b/package/src/RNCSliderNativeComponent.web.tsx @@ -69,7 +69,7 @@ const RCTSliderWebComponent = React.forwardRef( const containerSize = React.useRef({width: 0, height: 0}); const containerPositionX = React.useRef(0); const containerRef = forwardedRef || React.createRef(); - const hasBeenResized = React.useRef(false); + const containerPositionInvalidated = React.useRef(false); const [value, setValue] = React.useState(initialValue || minimumValue); const lastInitialValue = React.useRef(); @@ -145,18 +145,36 @@ const RCTSliderWebComponent = React.forwardRef( } }, [initialValue, updateValue, animatedValue]); - const onResize = () => { - hasBeenResized.current = true; - }; React.useEffect(() => { + const invalidateContainerPosition = () => { + containerPositionInvalidated.current = true; + }; + const onDocumentScroll = (e: Event) => { + if ( + // Avoid all other checks if already invalidated + !containerPositionInvalidated.current && + containerRef.current && + // @ts-ignore + e.target.contains(containerRef.current) + ) { + invalidateContainerPosition(); + } + }; //@ts-ignore - window.addEventListener('resize', onResize); + window.addEventListener('resize', invalidateContainerPosition); + //@ts-ignore + document.addEventListener('scroll', onDocumentScroll, {capture: true}); return () => { //@ts-ignore - window.removeEventListener('resize', onResize); + window.removeEventListener('resize', invalidateContainerPosition); + + //@ts-ignore + document.removeEventListener('scroll', onDocumentScroll, { + capture: true, + }); }; - }, []); + }, [containerRef]); const containerStyle = StyleSheet.compose( { @@ -221,8 +239,8 @@ const RCTSliderWebComponent = React.forwardRef( const getValueFromNativeEvent = (pageX: number) => { const {width = 1} = containerSize.current; - if (hasBeenResized.current) { - hasBeenResized.current = false; + if (containerPositionInvalidated.current) { + containerPositionInvalidated.current = false; updateContainerPositionX(); } const containerX = containerPositionX.current; From 986f4a52cb0453e0d1b69ce0e81469a8650a884a Mon Sep 17 00:00:00 2001 From: Bartosz Klonowski <70535775+BartoszKlonowski@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:28:39 +0100 Subject: [PATCH 2/2] Use const isAlreadyInvalidated instead of a comment --- package/src/RNCSliderNativeComponent.web.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/src/RNCSliderNativeComponent.web.tsx b/package/src/RNCSliderNativeComponent.web.tsx index 6867f862..4681b741 100644 --- a/package/src/RNCSliderNativeComponent.web.tsx +++ b/package/src/RNCSliderNativeComponent.web.tsx @@ -150,9 +150,9 @@ const RCTSliderWebComponent = React.forwardRef( containerPositionInvalidated.current = true; }; const onDocumentScroll = (e: Event) => { + const isAlreadyInvalidated = !containerPositionInvalidated.current; if ( - // Avoid all other checks if already invalidated - !containerPositionInvalidated.current && + isAlreadyInvalidated && containerRef.current && // @ts-ignore e.target.contains(containerRef.current)