The Tinder-style swipe card UI is an iconic and intuitive pattern for mobile apps. Whether you're building a habit tracker, a to-do list, or social app, giving users the ability to "swipe" through items is incredibly engaging.
But while many libraries can help you create a basic swipe deck, two major problems quickly appear:
In this guide, based on my video Make Swipe Card like Tinder/Bumble Deck in React Native, I'll show you exact method I used to solve these problems using the rn-swiper-list library and a clever setTimeout trick.
rn-swiper-list: The core library for the swipe deck.The first challenge is creating an infinite deck. When a user swipes the last card, we want the first card to reappear.
The logic I implemented is simple:
Here's where 90% of developers get stuck.
You set up the logic above, and it works... but it looks terible. When you swipe, there's a noticeable lag or jank [09:00].
Why does this happen? The swipe animation itself has a duration. The rn-swiper-list library defaults to an animation of about 500ms [09:12]. Your code, however, is updating the state (moving the card in the array) immediately.
You are forcing a state update and rerender while the card's exit animation is still playing. The two are fighting each other, resulting in a laggy, unprofessional-looking animation.
setTimeout TrickThe fix is surprisingly simple, but critical for a smooth user experience.
Do not update the state immediately. Wait for the animation to finish first.
Since we know the animation duration is 500ms, we wrap our state update function (moveToEnd) inside a setTimeout call with a 500ms delay.
By doing this [09:25], we let the card swipe off-screen completely. The animation finishes, and then the state updates silently in the background. The next card slides in, and the user experiences a perfectly smooth, seamless, and infinite loop.
What if you don't want external like or nope buttons? In my app, I wanted buttons inside the card itself to trigger the swipe.
You can achieve this by using a ref:
ref in your component: const swiperRef = useRef(null);ref to the swiper component: <Swiper ref={swiperRef} ../>ref down to your child card component: <HabitCard card={card} swiperRef={swiperRef} />HabitCard component, you can now add a Pressable button that calls the swiper's built-in methods:This gives you full control over the swipe deck, allowing you to build complex, custom UIs just like Tinder or Bumble.