I’m using React Native and have built an autoscrolling Flatlist using the component ref to access the scrollToIndex method.
All works fine, until I open the SideMenu which somehow causes flatList.current to become null, causing an application error.
I wonder if anyone know why this is occuring? Appreciate the help.
Thanks
App.js
import React, {useState} from 'react';
import { StyleSheet, Text, Image, View, SafeAreaView, ScrollView } from 'react-native';
import Background from './components/Background'
import Header from './components/Header'
import SideMenu from './components/SideMenu';
import SearchBar from './components/SearchBar'
import Swiper from './components/Swiper'
export default function App() {
const [ sideMenuOpen, setSideMenuOpen ] = useState(false)
const hamburgerHandler = () => {
sideMenuOpen ? setSideMenuOpen(false) : setSideMenuOpen(true)
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.background}>
<Background />
</View>
<Header sideMenuOpen={sideMenuOpen} setSideMenu={hamburgerHandler} />
<SideMenu sideMenuOpen={sideMenuOpen} />
<SearchBar />
<View style={sideMenuOpen ? styles.contentContainer : {height: '100%'}} >
<ScrollView>
<Swiper header={'Movies & TV: Coming Soon'} interval={6000} />
</ScrollView>
</View>
</SafeAreaView>
);
}
Swiper.js
import React, { useEffect, createRef } from "react";
import { View, Text, Image, FlatList, StyleSheet, Dimensions, } from 'react-native'
const Slider = props => {
const flatList = createRef()
const renderItem = ({ item }) => <Item content={item} />
const header = props.header ? <Text style={styles.header}>{props.header}</Text> : <Text>
</Text>
let currentSlide = 0
let timer
const _incrementSlider = (scale=0) => {
currentSlide+=scale
if (currentSlide > data.length-1) currentSlide = 0
flatList.current.scrollToIndex({
index: currentSlide,
animated: true
})
}
const _startAutoPlay = () => {
if (!props.interval) return
timer = setInterval(() => _incrementSlider(1), props.interval)
}
const _stopAutoPlay = () => {
clearInterval(timer)
timer = null
}
//ComponentDidMount
useEffect(() => {
console.log('mounted')
_startAutoPlay()
}, [])
//ComponentWillUnmount
useEffect(() => {
return () => {
console.log('unmounted')
_stopAutoPlay()
}
}, [])
return (
<View style={styles.container}>
{header}
<FlatList
data={data}
pagingEnabled={true}
horizontal={true}
renderItem={renderItem}
keyExtractor={item => item.id}
ref={flatList}
/>
</View>
)
}
>Solution :
Every time this component renders, you call createRef again, which creates a brand new ref. As a new ref, it has null for its .current property. createRef is not really meant for use in function components, and instead you should use useRef. It will create the ref just once, and return it to you on every render.
import React, { useEffect, useRef } from "react";
// ...
const flatList = useRef();