Skip to content

Commit ccb2d42

Browse files
fix(web): invalidate position on ancestor scroll (#472)
* fix(web): invalidate position on ancestor scroll Fixes #471. Added a test case to `example-web`. * Use const isAlreadyInvalidated instead of a comment Co-authored-by: Bartosz Klonowski <[email protected]>
1 parent 297eee6 commit ccb2d42

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

example-web/src/Examples.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {useState} from 'react';
22
// @ts-ignore
3-
import {Text, View, StyleSheet} from 'react-native';
3+
import {Text, View, StyleSheet, ScrollView} from 'react-native';
44
// @ts-ignore
55
import Slider, {SliderProps} from '@react-native-community/slider';
66

@@ -201,4 +201,29 @@ export const examples: Props[] = [
201201
return <SliderExample disabled value={0.6} />;
202202
},
203203
},
204+
{
205+
title: 'Slider in horizontal scroll view',
206+
render() {
207+
return (
208+
<ScrollView
209+
horizontal
210+
style={{
211+
paddingVertical: 50,
212+
borderStyle: 'dotted',
213+
borderWidth: 1,
214+
flexDirection: 'row',
215+
width: 300,
216+
}}
217+
contentContainerStyle={{ overflowX: 'scroll' }}
218+
>
219+
<View style={{ width: 400, paddingLeft: 100 }}>
220+
<SliderExample maximumValue={100} />
221+
<Text style={{ textAlign: 'right', width: 200 }}>
222+
Scroll right, then slide ➔
223+
</Text>
224+
</View>
225+
</ScrollView>
226+
);
227+
},
228+
},
204229
];

package/src/RNCSliderNativeComponent.web.tsx

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ const RCTSliderWebComponent = React.forwardRef(
7676
const containerSize = React.useRef({width: 0, height: 0});
7777
const containerPositionX = React.useRef(0);
7878
const containerRef = forwardedRef || React.createRef();
79-
const hasBeenResized = React.useRef(false);
79+
const containerPositionInvalidated = React.useRef(false);
8080
const [value, setValue] = React.useState(initialValue || minimumValue);
8181
const lastInitialValue = React.useRef<number>();
8282
const animationValues = React.useRef<AnimationValues>({
@@ -166,18 +166,36 @@ const RCTSliderWebComponent = React.forwardRef(
166166
}
167167
}, [initialValue, updateValue, animationValues]);
168168

169-
const onResize = () => {
170-
hasBeenResized.current = true;
171-
};
172169
React.useEffect(() => {
170+
const invalidateContainerPosition = () => {
171+
containerPositionInvalidated.current = true;
172+
};
173+
const onDocumentScroll = (e: Event) => {
174+
const isAlreadyInvalidated = !containerPositionInvalidated.current;
175+
if (
176+
isAlreadyInvalidated &&
177+
containerRef.current &&
178+
// @ts-ignore
179+
e.target.contains(containerRef.current)
180+
) {
181+
invalidateContainerPosition();
182+
}
183+
};
173184
//@ts-ignore
174-
window.addEventListener('resize', onResize);
185+
window.addEventListener('resize', invalidateContainerPosition);
186+
//@ts-ignore
187+
document.addEventListener('scroll', onDocumentScroll, {capture: true});
175188

176189
return () => {
177190
//@ts-ignore
178-
window.removeEventListener('resize', onResize);
191+
window.removeEventListener('resize', invalidateContainerPosition);
192+
193+
//@ts-ignore
194+
document.removeEventListener('scroll', onDocumentScroll, {
195+
capture: true,
196+
});
179197
};
180-
}, []);
198+
}, [containerRef]);
181199

182200
const containerStyle = StyleSheet.compose(
183201
{
@@ -242,8 +260,8 @@ const RCTSliderWebComponent = React.forwardRef(
242260
const getValueFromNativeEvent = (pageX: number) => {
243261
const {width = 1} = containerSize.current;
244262

245-
if (hasBeenResized.current) {
246-
hasBeenResized.current = false;
263+
if (containerPositionInvalidated.current) {
264+
containerPositionInvalidated.current = false;
247265
updateContainerPositionX();
248266
}
249267
const containerX = containerPositionX.current;

0 commit comments

Comments
 (0)