I'm excited to walk you through the development of a simple yet effective stories component using React. This component mimics the functionality of story-based content familiar from social media platforms, offering an engaging way to present a sequence of stories. Swiping is implemented using touch events, making the experience smooth and intuitive, especially on mobile devices. For desktop users, the component also supports mouse-based navigation.
The Stories component leverages React hooks and touch event listeners to create a smooth navigation experience. We'll be using useState
, useEffect
, and useRef
to manage state and side effects, and to reference DOM elements.
1import React, { useState, useEffect, useRef } from 'react';2
3const Stories = () => {4 const [currentStoryIndex, setCurrentStoryIndex] = useState<number>(0);5 const intervalRef = useRef<ReturnType<typeof setInterval>>();6
7 const goToPrevStory = () => {8 // Logic to navigate to the previous story9 setCurrentStoryIndex(prevIndex => Math.max(prevIndex - 1, 0));10 };11
12 const goToNextStory = () => {13 // Logic to navigate to the next story14 setCurrentStoryIndex(prevIndex => prevIndex + 1);15 };16
17 useEffect(() => {18 const container = document.getElementById('stories-container');19
20 if (container) {21 let touchStartX: number | null = null;22
23 const handleTouchStart: EventListener = (e) => {24 const touchEvent = e as TouchEvent;25 touchStartX = touchEvent.touches[0].clientX;26 };27
28 const handleTouchEnd: EventListener = (e) => {29 if (touchStartX === null) {30 return;31 }32
33 const touchEndX = (e as TouchEvent).changedTouches[0].clientX;34 const deltaX = touchEndX - touchStartX;35
36 if (deltaX > 50) {37 goToPrevStory();38 } else if (deltaX < -50) {39 goToNextStory();40 }41
42 touchStartX = null;43 };44
45 container.addEventListener('touchstart', handleTouchStart);46 container.addEventListener('touchend', handleTouchEnd);47
48 return () => {49 container?.removeEventListener('touchstart', handleTouchStart);50 container?.removeEventListener('touchend', handleTouchEnd);51 };52 }53 }, [goToPrevStory, goToNextStory]);54
55 return (56 <div id="stories-container">57 {/* Content of stories container */}58 </div>59 );60};61
62export default Stories;
State Management
currentStoryIndex
: Keeps track of the current story being displayed.intervalRef
: Utilised for managing intervals if you plan to auto-progress stories.Navigation Functions
goToPrevStory
: Decrements the currentStoryIndex
, ensuring it doesn't go below zero.goToNextStory
: Increments the currentStoryIndex
.Touch Event Handling
useEffect
: Adds touch event listeners to enable swipe navigation. On unmount, it cleans up these listeners.handleTouchStart
: Captures the initial touch position.handleTouchEnd
: Determines the swipe direction by comparing the end position with the start position, then navigates accordingly.deltaX
(difference between touchEndX
and touchStartX
) is greater than 50
, it indicates a swipe to the right, triggering goToPrevStory
.deltaX
is less than -50
, it indicates a swipe to the left, triggering goToNextStory
.Okay, now you have the basic structure of the Stories component with swipe navigation implemented. Now it's up to you to add the actual story content and styling to make it visually appealing. You can also extend the component with additional features like auto-progression, indicators, or custom animations. The possibilities are endless!
What I did for my project was to add an auto-play/auto-progression through the stories, by impleneneting a setInterval
that calls goToNextStory
every few seconds. This way, the stories automatically advance without user interaction. Story content can be dynamically rendered based on the currentStoryIndex
, allowing you to display different content for each story. Indicators can be added to show the current story index, giving users a visual cue of their progress.
Sign up to get updates when I write something new. No spam ever.
Subscribe to my Newsletter