Movie Swiping MVP: In-Depth Integration Guide
This document details the integration of the robust, scalable movie swiping MVP (Tinder-like interface) for React Native and web, focusing on backend filtering, cache invalidation, authentication, optimistic UI/UX, and error recovery.
1. Core Concepts
- Optimistic UI: Cards are removed from the stack immediately on swipe, before the API call completes. If the API call fails, the card is restored.
- Error Recovery: Errors are surfaced via a Snackbar with a retry button. The UI is never blocked by API latency.
- Backend Filtering: The backend ensures already-swiped movies are never shown again, using a scalable Postgres RPC.
- Pagination: Movies are fetched in batches. When the stack is low, the next page is fetched automatically.
- Authentication: All API calls include the user's access token. CORS/cookie issues are handled for both web and React Native.
- Cache Invalidation: React Query invalidates all relevant movie and swipe queries after a successful swipe.
2. Key Files & Components
SwipeStack.tsx: Main UI component for the swipe stack, optimistic updates, error handling, and pagination.useSwipeMutation.ts: Custom React Query mutation hook for swipes, supporting optimistic UI, rollback, and retry.- Backend:
/api/movies/randomand/api/swipesendpoints, with scalable filtering and robust error handling.
3. Optimistic UI & Error Recovery
useSwipeMutation.ts
- Accepts
onMutate,onError, andonSuccessfor full optimistic UI support. - Exposes mutation state (
isPending,error, etc.) for UI feedback. - Supports retry and rollback via React Query context.
Example Usage:
const swipeMutation = useSwipeMutation({
onMutate: async (swipeData) => {
// Optimistically remove card
const swipedMovie = cardStack[cardStack.length - 1]
setCardStack((prev) => prev.slice(0, -1))
return { swipedMovie }
},
onError: (err, _variables, context) => {
setSnackbarError(err.message)
if (context?.swipedMovie) setCardStack((prev) => [...prev, context.swipedMovie])
},
onSuccess: () => setSnackbarError(null),
})
SwipeStack.tsx
- Handles swipe gestures, optimistic updates, and error display.
- Shows a Snackbar for errors, with a retry button that re-attempts the last swipe.
- Only shows a loading overlay when fetching more movies (not during each swipe).
Key Integration Points:
handleSwipe(direction): Triggers the mutation and updates local state.retryLastSwipe(): Retries the last failed swipe and clears errors.Snackbar: Appears at the bottom for errors, auto-hides after 4s, and supports manual retry.
4. Backend Filtering & Pagination
/api/movies/randomuses a Postgres RPC to fetch only unswiped movies for the user, supporting efficient pagination and filtering./api/swipesrecords swipes, with robust error handling and user context.- The frontend never shows already-swiped movies, even across sessions.
5. Authentication
- All API calls include the user's access token in the
Authorizationheader. - Handles CORS/cookie issues for both web and React Native.
- Uses a custom
useAuthQueryhook to access the current session.
6. Cache Invalidation
- After a successful swipe, React Query invalidates all
random-moviesqueries to ensure the next fetch is up-to-date. - This ensures that the user never sees the same movie twice, even if they navigate away and return.
7. Best Practices
- Optimistic UI: Always update the UI first, then sync with the backend. Use React Query's
onMutate/contextfor rollback. - Error Recovery: Surface errors in a non-blocking way (snackbar, not modal). Allow retrying failed actions.
- Pagination: Pre-fetch the next page before the stack is empty for a seamless experience.
- Authentication: Always include the access token, and handle session expiration gracefully.
- Debugging: Use detailed debug logs on both frontend and backend to trace user actions and API responses.
8. Example Integration Flow
- User swipes a card.
- Card is immediately removed from the stack (optimistic update).
- API call is made to record the swipe.
- If the call succeeds, cache is invalidated and the UI remains unchanged.
- If the call fails, the card is restored and a snackbar appears with the error and a retry button.
- When the stack is low, the next page of movies is fetched automatically.
9. Further Improvements
- Add more unit/integration tests for swipe logic and API integration.
- Expand accessibility and responsiveness.
- Add more advanced UX patterns (e.g., undo, swipe animations, etc.).
- Expand documentation with more React Native/web-specific tips.
For more details, see the code in SwipeStack.tsx and useSwipeMutation.ts, and the backend API routes.