A React Native app built with Expo and React Relay (against a mock service) for managing a collection of baseball cards. Users can view cards, see detailed information, and like their favorite cards.
The like button demonstrates immediate feedback:
- Heart icon changes instantly on tap
- Loading indicator shows during request
- Reverts on error (e.g., when offline)
- View list of baseball cards
- Card details view
- Like/unlike cards with instant feedback
- Optimistic UI updates
- Immediate UI response without waiting for server
- Smooth user experience for like/unlike actions
- Graceful error handling and state reversion
- Offline capabilities
- Image caching
- React Native - A framework for building native apps using React
- Expo/EAS - Platform and build service for React Native apps
- React Relay - Production-ready GraphQL client for React
- TypeScript - JavaScript with syntax for types
- React Navigation - Routing and navigation for React Native apps
- React Native Paper - Material Design components for React Native
- Node.js v18 or higher - JavaScript runtime environment
- npm or yarn - Package managers for Node.js
- Expo CLI - Command line tool for Expo development
- iOS Simulator (for iOS development)
- macOS - Required for iOS development
- Xcode (latest version) - iOS development environment
- Android Studio (for Android development)
- Android SDK - Software development kit for Android
- Android Emulator - Virtual device for testing Android apps
-
Clone the repository:
git clone https://github.com/kbanashek/RNCardList.git cd RNCardList
-
Install dependencies:
npm install
-
Start the development server:
npm start
-
Open the app:
- For iOS: Press
i
in the terminal or runnpm run ios
- For Android: Press
a
in the terminal or runnpm run android
- For iOS: Press
-
Unit Tests
npm run test
The app uses a mock GraphQL service for data. All network requests are handled through Relay, with offline support and optimistic updates.
The app implements optimistic UI updates to provide instant feedback for user actions:
// Example from useToggleCardLike hook
commit({
variables: { input: { cardId } },
// Update UI immediately
optimisticResponse: {
toggleCardLike: {
card: {
id: cardId,
isLiked: true,
},
},
},
// Revert UI if server request fails
onError: (error) => {
// Handle error state
},
});
This pattern:
- Updates UI immediately when user takes action
- Sends request to server in background
- Handles errors by reverting UI if needed
The optimistic updates are implemented using React Relay's mutation API:
-
State Management:
const [state, setState] = useState<MutationState>({ loadingCardIds: new Set(), // Track loading state per card error: null, // Handle errors globally });
-
Loading States:
- Each card tracks its own loading state
- UI can show loading indicators while request is pending
- Prevents duplicate requests for the same card
-
Error Handling:
- Global error state for user feedback
- Automatic UI reversion on failure
- Proper cleanup of loading states
The LikeButton
component integrates with the optimistic update system:
const LikeButton = ({ cardId, isLiked }) => {
const { toggleLike, isLoading } = useToggleCardLike();
return (
<IconButton
icon={isLiked ? "heart" : "heart-outline"}
onPress={() => toggleLike(cardId)}
disabled={isLoading}
// Show loading state while request is pending
loading={isLoading}
/>
);
};
- Enable network debugging in Chrome DevTools
- Like a card and verify:
- UI updates immediately
- Network request is sent in background
- UI remains updated after request completes
- Test error handling:
- Enable airplane mode
- Like a card
- Verify UI reverts when offline
- Load the app with network connection
- Enable airplane mode
- Verify:
- Cards are still visible
- Images load from cache
- Like/unlike actions show proper error states
- Network status banner appears
- Re-enable network:
- Banner should disappear
- Any pending actions should resolve
The app uses several strategies to provide a seamless offline experience:
-
Data Persistence:
- Relay stores query data in memory cache
- Images are pre-cached on first load
- Network state is monitored via NetInfo
-
UI Feedback:
- Network status banner shows offline state
- Loading states indicate pending actions
- Error states show when actions fail
- Cached data is used when offline
-
Error Recovery:
- Automatic retry when network returns
- Clear error states on reconnection
- Preserve user actions when possible