A small, production-style React Native app (no TypeScript) that demonstrates:
- API fetching with loading and error handling
- Custom hook to detect online/offline network status
- React Navigation with parameter passing between screens
- Login form with simple validation
- Global auth state with Redux Toolkit (login/logout gating)
- Theming with gradients and a shared color palette
This project was created with Expo for easy setup and running on Windows, Android, iOS, and Web (development).
# 1) Install dependencies (already installed during setup)
# If needed, you can run npm install again
npm install
# 2) Start the Expo dev server
npx expo start
# 3) Run on your device/emulator
# - Press 'a' in the Expo CLI to open Android emulator
# - Or scan the QR code with the Expo Go app on your phone
If you haven’t installed Android Studio/emulator yet, you can still run on a physical device using Expo Go.
- React Native + Expo
- React Navigation (native-stack)
- Redux Toolkit + React-Redux
- @react-native-community/netinfo
- expo-linear-gradient
ReactNativeTask/
App.js
src/
components/
NetworkBanner.js
hooks/
useNetworkStatus.js
navigation/
AppNavigator.js
screens/
LoginScreen.js
HomeScreen.js
DetailsScreen.js
store/
authSlice.js
index.js
theme/
colors.js
- Unauthenticated state (Login)
- On launch, the app checks Redux state (auth.isAuthenticated).
- If false, it shows LoginScreen.
- The login form validates:
- Email must include "@"
- Password must be at least 6 characters
- On valid submit, it dispatches auth/login with the entered email.
- The global state flips to isAuthenticated: true and stores the user email.
- Authenticated state (Home + Details)
- Once authenticated, AppNavigator shows the Home screen (and Details screen in the stack).
- HomeScreen fetches a list of users from https://jsonplaceholder.typicode.com/users.
- Shows an ActivityIndicator while loading.
- Displays errors with a helpful message and supports pull-to-refresh.
- Tapping a user navigates to DetailsScreen with the full user object passed as a route param.
- DetailsScreen renders a details card containing email, username, phone, website, company and address.
- Logout
- HomeScreen header shows a Logout button.
- Pressing it dispatches auth/logout, resets auth state, and the navigator returns to LoginScreen.
- Online/Offline banner
- A banner at the top shows "Online" or "Offline" based on NetInfo events in a custom hook.
- This is always visible because the banner is rendered above the stack navigator.
- src/navigation/AppNavigator.js creates a native stack with two flows:
- Auth flow: LoginScreen (when isAuthenticated is false)
- App flow: HomeScreen and DetailsScreen (when isAuthenticated is true)
- The header is styled with a primary color for a stronger visual identity.
- src/store/index.js configures the Redux store with a single slice: auth.
- src/store/authSlice.js defines:
- state: { isAuthenticated: false, user: null }
- reducers:
- login({ email }): sets isAuthenticated true and stores the email
- logout(): resets isAuthenticated to false and clears user
- Usage in the UI:
- LoginScreen dispatches login on successful validation.
- HomeScreen header button dispatches logout.
Example (illustrative only):
// On submit in LoginScreen
dispatch(login({ email }))
// On header logout press in HomeScreen
dispatch(logout())
- Fetches from https://jsonplaceholder.typicode.com/users
- Manages UI states:
- loading: shows ActivityIndicator
- error: shows an error box with retry guidance (pull-to-refresh)
- success: shows a FlatList of users (name + email)
- Pull-to-refresh triggers a re-fetch.
Example (illustrative):
const res = await fetch('https://jsonplaceholder.typicode.com/users')
if (!res.ok) throw new Error('Failed to fetch users')
const data = await res.json()
setUsers(Array.isArray(data) ? data : [])
- HomeScreen navigates with navigation.navigate('Details', { user })
- DetailsScreen reads route.params.user and renders it.
Example (illustrative):
navigation.navigate('Details', { user: item })
// ...
const { user } = route.params || {}
- src/hooks/useNetworkStatus.js subscribes to NetInfo.addEventListener.
- Returns true when connected and internet is reachable; false otherwise.
- src/components/NetworkBanner.js uses the hook and displays an Online/Offline banner with themed colors.
- expo-linear-gradient provides soft gradients for screen backgrounds.
- src/theme/colors.js centralizes the palette (primary, secondary, background gradient stops, text colors, and state colors).
- Components use a card style with subtle shadows and rounded corners.
- The navigator header uses the primary color for contrast.
# from the project root
npx expo start
# press 'a' to open Android emulator, or scan QR with Expo Go
On Windows, if Android emulator isn’t configured, install Android Studio and create a virtual device, or use Expo Go on your phone.
- Stuck on “Connecting” in Expo Go:
- Ensure your phone and PC are on the same network.
- Try switching the connection mode in the Expo CLI (press 'c' to toggle between tunnel/lan).
- Metro bundler cache issues:
npx expo start -c
- Android build fails to launch:
- Ensure ANDROID_HOME is set and that you can open the emulator from Android Studio.
- Add persistent auth (e.g., redux-persist) so the user stays logged in after app restarts.
- Add search/filter on the users list.
- Replace the simple email validation with a more robust regex.
- Add unit tests for the hook and the auth slice.
MIT (or your preferred license)