Kelvan Ince
Kelvan Ince

Reputation: 88

React Native: Why is this useRef hook not auto scrolling

I am trying to auto-scroll between four images using the useRef hook which identifies the target using a state value called 'selected'.

I am getting unexpected behaviour in that the auto-scroll is erratic, usually leaving out the third image it should be scrolling to.

const [selected, setSelected] = useState(0);
const scrollRef = useRef(null);

const setSelectedIndex = e => {
    const viewSize = e.nativeEvent.layoutMeasurement.width;
    const contentOffset = e.nativeEvent.contentOffset.x;
    const selectedIndex = Math.floor(contentOffset / viewSize);
    setSelected(selectedIndex);
}

useEffect(() => {
    setInterval(() => {
        setSelected(prev => prev + 1);
        scrollRef.current.scrollTo({
            animated: true,
            y: 0,
            x: DEVICE_WIDTH * selected
        });
    }, 10000);
}, [selected]);

return (
    <View style={{ height: '100%', width: '100%' }}>
        <ScrollView
            horizontal
            pagingEnabled
            onMomentumScrollEnd={setSelectedIndex}
            ref={scrollRef}
        >
            {images.map(image => (
                <Image
                    key={image}
                    source={image}
                    style={styles.backgroundImage}
                />
            ))}
        </ScrollView>
        <View style={styles.circleDiv}>
            {
                images.map((img, i) => (
                    <View
                        key={img}
                        style={[styles.whiteCircle, { opacity: i === selected ? 0.5 : 1 }]}
                    />
                ))
            }
        </View>
    </View>
);

If it helps, I have built it using componentDidMount which works as expected.

scrollRef = createRef();

componentDidMount = () => {
    setInterval(() => {
        this.setState({
            prev => ({ selected: prev.selected + 1 }),
            () => {
                this.scrollRef.current.scrollTo({
                    animated: true,
                    y: 0,
                    x: DEVICE_WIDTH * this.state.selected
                });
            }
            });
}, 5000);
    }

Upvotes: 1

Views: 1091

Answers (1)

Thisara Sudaraka
Thisara Sudaraka

Reputation: 551

try like this,

  • use useRef() instead of createRef()

  • return new state from setSelected arrow function

  • use setTimeout instead of setInterval

    const scrollRef = useRef()
    
    useEffect(() => {
      setTimeout(() => {
        setSelected((prev) => (
          prev == slidesArray.length - 1 ? 0 : prev + 1
        ))
        if (scrollRef.current) {
          scrollRef.current.scrollTo({
            animated: true,
            y: 0,
            x: DEVICE_WIDTH * (selected +1)
          });
        }
    
      }, 5000);
    }, [selected])
    

Upvotes: 0

Related Questions