Lists are a cornerstone feature in various applications, from productivity tools to all apps. In this guide, we’ll walk through building a single-slider in React Native that allows users to select hours, minutes, and seconds using scrollable lists powered by FlatList. We’ll also include a reset button to restore the List to its default state. We are going to take the Time Selector example for further explanation.
A FlatList is a React Native component used to efficiently render large lists of data. It is a very optimized component meant for scrolling through a large number of items in a performant way, especially when compared to using traditional components like ScrollView.
Key Features of FlatList:
1. Efficient Rendering:
2. Virtualized List:
3. Customizable Rendering:
4. Performance Optimizations:
5. Scrolling:
6. Flexibility:
Custom Timer Selector:
Users can set hours, minutes, and seconds using scrollable lists.
Each list is built using a FlatList component with smooth scrolling and snapping to intervals.
Real-Time Feedback:
The selected values are displayed dynamically.
The total time is calculated in seconds.
Reset Timer Functionality:
A dedicated "Reset" button reverts the timer to its initial state.
The timer lists scroll back to the top automatically.
Before diving into the code, ensure you have a React Native project set up. You can create a new project using the following command:
npx react-native init TimerApp
const [hours] = useState(Array.from({ length: 23 }, (_, i) => i + 1));
const [minutes] = useState(Array.from({ length: 59 }, (_, i) => i + 1));
const [seconds] = useState(Array.from({ length: 59 }, (_, i) => i + 1));
const [selectedHour, setSelectedHour] = useState(1);
const [selectedMinute, setSelectedMinute] = useState(1);
const [selectedSecond, setSelectedSecond] = useState(1);
const hourRef = useRef(null);
const minutesRef = useRef(null);
const secondsRef = useRef(null);
The timer will consist of three scrollable lists—one each for hours, minutes, and seconds. We’ll use the FlatList component for smooth scrolling and snapping.
Here’s the structure of our timer UI:
Header
const Header = () => {
return (
<View style={styles.header}>
<Text style={styles.headerText}>Set Timer</Text>
<TouchableOpacity onPress={resetTimer} style={styles.resetButton}>
<Text style={styles.resetText}>Reset</Text>
</TouchableOpacity>
</View>
);
};
FlatList:
<View style={styles.timerBox}>
<Text style={styles.hourMinuteText}>Hour</Text>
<View style={styles.listContainer}>
<FlatList
ref={hourRef}
data={hours}
renderItem={renderTimer}
getItemLayout={getItemLayout}
showsVerticalScrollIndicator={false}
decelerationRate="fast"
snapToInterval={60}
snapToAlignment="center"
onScroll={handleScroll(setSelectedHour, hours.length, 'hour')}
initialScrollIndex={selectedHour - 1}
onScrollToIndexFailed={(info) => {
console.warn("Scroll to index failed", info);
}}
/>
</View>
</View>
Create same Flatlist for Minutes and Seconds same as Hour
Show Result: <View style={{
height: 120,
width: deviceWidth
}}>
<View style={styles.timeContainer}>
<Text style={styles.timeText}>Hours : {selectedHour}</Text>
</View>
<View style={styles.timeContainer}>
<Text style={styles.timeText}>Minutes : {selectedMinute}</Text>
</View>
<View style={styles.timeContainer}>
<Text style={styles.timeText}>Seconds : {selectedSecond}</Text>
</View>
<View style={{ height: 2, width: deviceWidth, backgroundColor: 'lightgrey' }} />
<View style={styles.timeContainer}>
<Text style={styles.timeText}>Total Seconds : {timeToSeconds(selectedHour, selectedMinute, selectedSecond)}</Text>
</View>
</View>
Each list is bound to a FlatList component and dynamically updates the selected value based on user interaction. You can modify your Stylesheet As your requirements
// Scroll all three FlatList components to the top.
const scrollToTop = () => {
hourRef.current?.scrollToIndex({ animated: true, index: 0 });
minutesRef.current?.scrollToIndex({ animated: true, index: 0 });
secondsRef.current?.scrollToIndex({ animated: true, index: 0 });
};
// Handle scroll and update state values.
const handleScroll = (setSelected, dataLength, type) => (event) => {
const offsetY = event.nativeEvent.contentOffset.y;
const index = Math.round(offsetY / 60); // Assuming 60 is the item height.
if (index >= 0 && index < dataLength) {
setSelected(index + 1); // +1 assuming your data starts from 1, not 0.
}
};
const checkRange = (item) => (item > 9 ? item : '0' + item);
// Renders a single timer item.
const renderTimer = ({ item }) => (
<TouchableOpacity activeOpacity={0.7} style={styles.timerItem}>
<Text style={styles.timerText}>{checkRange(item)}</Text>
</TouchableOpacity>
);
// Used to optimize FlatList by providing the exact height of a single item and the offset of that item.
const getItemLayout = (_, index) => ({
length: 60, // Assuming 60 is the item height.
offset: 60 * index,
index,
});
// Returns a separator element that is used to separate the hours, minutes, seconds in the timer.
const Separator = () => (
<View style={styles.separator}>
<Text style={styles.mark}>:</Text>
</View>
);
// Converts a given time in hours, minutes, and seconds to the total number of seconds.
const timeToSeconds = (hours, minutes, seconds) => {
return hours * 3600 + minutes * 60 + seconds;
};
// Resets the timer to the starting state by scrolling all three FlatList components to the top and setting the hours, minutes, and seconds to 1.
const resetTimer = () => {
scrollToTop();
setSelectedHour(1);
setSelectedMinute(1);
setSelectedSecond(1);
};
You can also add reset timer feature as needed
const resetTimer = () => {
// Scroll all lists to the top
hourRef.current?.scrollToIndex({ animated: true, index: 0 });
minuteRef.current?.scrollToIndex({ animated: true, index: 0 });
secondRef.current?.scrollToIndex({ animated: true, index: 0 });
// Reset selected values
setSelectedHour(1);
setSelectedMinute(1);
setSelectedSecond(1);
// Show a toast notification
Toast.show('Timer reset successfully!', Toast.SHORT);
};
This tutorial explains how to make a custom timer with a reset functionality in React Native. The application offers a smooth user-friendly interface and real-time updates. This feature can be extended further to add a countdown or alert when the timer reaches zero.
Ready to transform your business with our technology solutions? Contact Us today to Leverage Our React Native Expertise.