Skip to content

Commit 83d21dd

Browse files
committed
fix(web): invalidate position on ancestor scroll
Fixes #471. Added a test case to `example-web`.
1 parent fa1f9ea commit 83d21dd

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
@@ -69,7 +69,7 @@ const RCTSliderWebComponent = React.forwardRef(
6969
const containerSize = React.useRef({width: 0, height: 0});
7070
const containerPositionX = React.useRef(0);
7171
const containerRef = forwardedRef || React.createRef();
72-
const hasBeenResized = React.useRef(false);
72+
const containerPositionInvalidated = React.useRef(false);
7373
const [value, setValue] = React.useState(initialValue || minimumValue);
7474
const lastInitialValue = React.useRef<number>();
7575

@@ -145,18 +145,36 @@ const RCTSliderWebComponent = React.forwardRef(
145145
}
146146
}, [initialValue, updateValue, animatedValue]);
147147

148-
const onResize = () => {
149-
hasBeenResized.current = true;
150-
};
151148
React.useEffect(() => {
149+
const invalidateContainerPosition = () => {
150+
containerPositionInvalidated.current = true;
151+
};
152+
const onDocumentScroll = (e: Event) => {
153+
if (
154+
// Avoid all other checks if already invalidated
155+
!containerPositionInvalidated.current &&
156+
containerRef.current &&
157+
// @ts-ignore
158+
e.target.contains(containerRef.current)
159+
) {
160+
invalidateContainerPosition();
161+
}
162+
};
152163
//@ts-ignore
153-
window.addEventListener('resize', onResize);
164+
window.addEventListener('resize', invalidateContainerPosition);
165+
//@ts-ignore
166+
document.addEventListener('scroll', onDocumentScroll, {capture: true});
154167

155168
return () => {
156169
//@ts-ignore
157-
window.removeEventListener('resize', onResize);
170+
window.removeEventListener('resize', invalidateContainerPosition);
171+
172+
//@ts-ignore
173+
document.removeEventListener('scroll', onDocumentScroll, {
174+
capture: true,
175+
});
158176
};
159-
}, []);
177+
}, [containerRef]);
160178

161179
const containerStyle = StyleSheet.compose(
162180
{
@@ -221,8 +239,8 @@ const RCTSliderWebComponent = React.forwardRef(
221239
const getValueFromNativeEvent = (pageX: number) => {
222240
const {width = 1} = containerSize.current;
223241

224-
if (hasBeenResized.current) {
225-
hasBeenResized.current = false;
242+
if (containerPositionInvalidated.current) {
243+
containerPositionInvalidated.current = false;
226244
updateContainerPositionX();
227245
}
228246
const containerX = containerPositionX.current;

0 commit comments

Comments
 (0)