Staring at React Native code feels comfortable. Watching tutorials makes sense. But when it’s time to build your own app, suddenly everything goes blank – and that feeling can be really discouraging. You’re not alone, and this post exists to turn that blank moment into a breakthrough.
Here are 100 React Native practice problems with clear, step-by-step solutions that take you from understanding code to writing it with genuine confidence. You’ll start with simple components, JSX, and styling, then master state management, navigation, FlatLists, API calls, hooks, and even basic animations. Each problem is written in plain, everyday language. You try the challenge yourself first, then check the solution and truly learn the why behind every line.
Why is deliberate practice so powerful? Because app development is a hands-on skill. Every problem you solve builds muscle memory, sharpens your debugging instinct, and transforms scattered knowledge into the ability to launch real apps from scratch. That’s what makes you valuable – not just someone who “knows React Native,” but someone who can build, problem-solve, and deliver.
Whether you’re falling in love with mobile development or preparing for a front-end interview, these exercises will make you feel prepared, capable, and excited. Pick a problem, open your editor, and experience that amazing “I’m really building this!” moment today.
Also try it: 100 Java practice problems with solutions
1. Create a React Native component that displays “Hello, World!” on the screen.
jsx
import React from 'react';
import { Text, View } from 'react-native';
const App = () => (
<View><Text>Hello, World!</Text></View>
);
export default App;
2. Use the useState hook to create a counter that increments when a button is pressed.
jsx
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>{count}</Text>
<Button title="Increment" onPress={() => setCount(count + 1)} />
</View>
);
};
export default Counter;
3. Display a list of items using FlatList with hardcoded data.
jsx
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const data = [{ id: '1', name: 'Apple' }, { id: '2', name: 'Banana' }];
const ListExample = () => (
<FlatList data={data} renderItem={({ item }) => <Text>{item.name}</Text>} keyExtractor={item => item.id} />
);
export default ListExample;
4. Create a functional component that accepts props (name) and displays a greeting.
jsx
import React from 'react';
import { Text } from 'react-native';
const Greeting = ({ name }) => <Text>Hello, {name}!</Text>;
export default Greeting;
5. Use TextInput to capture user input and display it below.
jsx
import React, { useState } from 'react';
import { TextInput, Text, View } from 'react-native';
const InputDisplay = () => {
const [text, setText] = useState('');
return (
<View>
<TextInput placeholder="Type here" onChangeText={setText} />
<Text>You typed: {text}</Text>
</View>
);
};
export default InputDisplay;
6. Apply a custom style using StyleSheet to center text and set background color.
jsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const StyledBox = () => (
<View style={styles.container}>
<Text style={styles.text}>Centered text</Text>
</View>
);
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'lightblue' },
text: { fontSize: 20, color: 'darkblue' }
});
export default StyledBox;
7. Use TouchableOpacity to change background color on press (simulate).
jsx
import React, { useState } from 'react';
import { TouchableOpacity, Text, View, StyleSheet } from 'react-native';
const ColorChanger = () => {
const [bgColor, setBgColor] = useState('white');
return (
<TouchableOpacity style={[styles.box, { backgroundColor: bgColor }]} onPress={() => setBgColor('lightgreen')}>
<Text>Tap to change color</Text>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({ box: { padding: 20, margin: 20 } });
export default ColorChanger;
8. Make an HTTP GET request using fetch and display the result.
jsx
import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';
const FetchExample = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(res => res.json())
.then(json => setData(json));
}, []);
return <View>{data && <Text>{data.title}</Text>}</View>;
};
export default FetchExample;
9. Use useEffect to log a message when the component mounts.
jsx
import React, { useEffect } from 'react';
import { Text } from 'react-native';
const MountLogger = () => {
useEffect(() => {
console.log('Component mounted');
}, []);
return <Text>Check console</Text>;
};
export default MountLogger;
10. Create a toggle button that shows/hides a text using useState.
jsx
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const ToggleText = () => {
const [visible, setVisible] = useState(false);
return (
<View>
<Button title="Toggle" onPress={() => setVisible(!visible)} />
{visible && <Text>Now you see me!</Text>}
</View>
);
};
export default ToggleText;
11. Implement a simple form with two TextInputs (email and password) and a submit button.
jsx
import React, { useState } from 'react';
import { View, TextInput, Button, Alert } from 'react-native';
const LoginForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = () => Alert.alert(`Email: ${email}, Password: ${password}`);
return (
<View>
<TextInput placeholder="Email" onChangeText={setEmail} />
<TextInput placeholder="Password" secureTextEntry onChangeText={setPassword} />
<Button title="Submit" onPress={handleSubmit} />
</View>
);
};
export default LoginForm;
12. Use FlatList with a separator component.
jsx
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const data = [{ id: '1', name: 'A' }, { id: '2', name: 'B' }];
const ItemSeparator = () => <View style={{ height: 1, backgroundColor: 'gray' }} />;
const ListWithSeparator = () => (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={item => item.id}
ItemSeparatorComponent={ItemSeparator}
/>
);
export default ListWithSeparator;
13. Create a custom hook useToggle that returns a boolean and a toggle function.
jsx
import { useState } from 'react';
const useToggle = (initial = false) => {
const [value, setValue] = useState(initial);
const toggle = () => setValue(v => !v);
return [value, toggle];
};
// Usage in component
const ToggleComponent = () => {
const [isOn, toggle] = useToggle();
return <Text onPress={toggle}>{isOn ? 'ON' : 'OFF'}</Text>;
};
export default ToggleComponent;
14. Use ScrollView to display a long list of text items.
jsx
import React from 'react';
import { ScrollView, Text } from 'react-native';
const LongScroll = () => (
<ScrollView>
{[...Array(50)].map((_, i) => <Text key={i}>Item {i + 1}</Text>)}
</ScrollView>
);
export default LongScroll;
15. Apply a linear gradient using expo-linear-gradient (assume installed).
jsx
import React from 'react';
import { LinearGradient } from 'expo-linear-gradient';
import { Text } from 'react-native';
const GradientBox = () => (
<LinearGradient colors={['#4c669f', '#3b5998']} style={{ padding: 20 }}>
<Text>Gradient Background</Text>
</LinearGradient>
);
export default GradientBox;
16. Use Alert.alert to show a confirmation before deleting an item.
jsx
import { Alert, Button } from 'react-native';
const DeleteButton = () => {
const confirmDelete = () => {
Alert.alert('Delete', 'Are you sure?', [
{ text: 'Cancel' },
{ text: 'OK', onPress: () => console.log('Deleted') }
]);
};
return <Button title="Delete" onPress={confirmDelete} />;
};
export default DeleteButton;
17. Implement a simple tab navigation using @react-navigation/bottom-tabs.
jsx
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Text } from 'react-native';
const HomeScreen = () => <Text>Home</Text>;
const SettingsScreen = () => <Text>Settings</Text>;
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
18. Use useRef to focus a TextInput on button press.
jsx
import React, { useRef } from 'react';
import { TextInput, Button, View } from 'react-native';
const FocusInput = () => {
const inputRef = useRef(null);
return (
<View>
<TextInput ref={inputRef} placeholder="Focus me" />
<Button title="Focus" onPress={() => inputRef.current.focus()} />
</View>
);
};
export default FocusInput;
19. Display a loading indicator while fetching data.
jsx
import React, { useState, useEffect } from 'react';
import { ActivityIndicator, Text, View } from 'react-native';
const LoadingData = () => {
const [loading, setLoading] = useState(true);
useEffect(() => {
setTimeout(() => setLoading(false), 2000);
}, []);
return loading ? <ActivityIndicator size="large" /> : <Text>Data loaded</Text>;
};
export default LoadingData;
20. Use SafeAreaView to avoid notches on modern phones.
jsx
import React from 'react';
import { SafeAreaView, Text } from 'react-native';
const SafeAreaExample = () => (
<SafeAreaView style={{ flex: 1 }}>
<Text>Safe area content</Text>
</SafeAreaView>
);
export default SafeAreaExample;
21. Create a component that uses Image to display a local image.
jsx
import React from 'react';
import { Image } from 'react-native';
const LocalImage = () => <Image source={require('./assets/icon.png')} style={{ width: 50, height: 50 }} />;
export default LocalImage;
22. Use Modal to show a popup when a button is pressed.
jsx
import React, { useState } from 'react';
import { Modal, View, Text, Button } from 'react-native';
const PopupModal = () => {
const [visible, setVisible] = useState(false);
return (
<View>
<Button title="Show Modal" onPress={() => setVisible(true)} />
<Modal visible={visible} transparent animationType="slide">
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(0,0,0,0.5)' }}>
<View style={{ backgroundColor: 'white', padding: 20 }}>
<Text>Modal Content</Text>
<Button title="Close" onPress={() => setVisible(false)} />
</View>
</View>
</Modal>
</View>
);
};
export default PopupModal;
23. Save and retrieve data using AsyncStorage (React Native community).
jsx
import React, { useState, useEffect } from 'react';
import { View, TextInput, Button, Text } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
const StorageExample = () => {
const [name, setName] = useState('');
const [saved, setSaved] = useState('');
useEffect(() => {
AsyncStorage.getItem('name').then(val => setSaved(val || ''));
}, []);
const saveName = async () => {
await AsyncStorage.setItem('name', name);
setSaved(name);
};
return (
<View>
<TextInput placeholder="Enter name" onChangeText={setName} />
<Button title="Save" onPress={saveName} />
<Text>Saved: {saved}</Text>
</View>
);
};
export default StorageExample;
24. Use StatusBar to set the status bar style to light content.
jsx
import React from 'react';
import { StatusBar, View } from 'react-native';
const StatusBarExample = () => (
<View>
<StatusBar barStyle="light-content" />
</View>
);
export default StatusBarExample;
25. Implement a horizontal FlatList using horizontal prop.
jsx
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const data = [{ id: '1', color: 'red' }, { id: '2', color: 'blue' }];
const HorizontalList = () => (
<FlatList horizontal data={data} renderItem={({ item }) => <View style={{ width: 100, height: 100, backgroundColor: item.color }} />} keyExtractor={item => item.id} />
);
export default HorizontalList;
26. Use Dimensions API to get screen width and set element size.
jsx
import React from 'react';
import { Dimensions, View } from 'react-native';
const { width } = Dimensions.get('window');
const FullWidthBox = () => <View style={{ width: width, height: 50, backgroundColor: 'green' }} />;
export default FullWidthBox;
27. Create a button that opens a URL in the device browser using Linking.
jsx
import React from 'react';
import { Button, Linking } from 'react-native';
const OpenLink = () => (
<Button title="Open Google" onPress={() => Linking.openURL('https://www.google.com')} />
);
export default OpenLink;
28. Use useCallback to memoize a function passed to a child component.
jsx
import React, { useState, useCallback } from 'react';
import { Button, Text } from 'react-native';
const Child = ({ onPress }) => <Button title="Press" onPress={onPress} />;
const Parent = () => {
const [count, setCount] = useState(0);
const handlePress = useCallback(() => setCount(c => c + 1), []);
return (
<>
<Text>{count}</Text>
<Child onPress={handlePress} />
</>
);
};
export default Parent;
29. Handle network errors in fetch with .catch and display error message.
jsx
import React, { useState } from 'react';
import { Button, Text } from 'react-native';
const ErrorHandling = () => {
const [error, setError] = useState('');
const fetchData = () => {
fetch('https://invalid.url')
.then(res => res.json())
.catch(err => setError(err.message));
};
return (
<>
<Button title="Fetch" onPress={fetchData} />
{error ? <Text>Error: {error}</Text> : null}
</>
);
};
export default ErrorHandling;
30. Implement pull-to-refresh using RefreshControl inside FlatList.
jsx
import React, { useState } from 'react';
import { FlatList, RefreshControl, Text } from 'react-native';
const PullToRefresh = () => {
const [refreshing, setRefreshing] = useState(false);
const [data, setData] = useState(['Item 1', 'Item 2']);
const onRefresh = () => {
setRefreshing(true);
setTimeout(() => {
setData(['Item 1', 'Item 2', 'Item 3']);
setRefreshing(false);
}, 1000);
};
return (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item}</Text>}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
/>
);
};
export default PullToRefresh;
31. Use Switch component to toggle a boolean state.
jsx
import React, { useState } from 'react';
import { Switch, Text, View } from 'react-native';
const ToggleSwitch = () => {
const [isEnabled, setIsEnabled] = useState(false);
return (
<View>
<Switch value={isEnabled} onValueChange={setIsEnabled} />
<Text>{isEnabled ? 'ON' : 'OFF'}</Text>
</View>
);
};
export default ToggleSwitch;
32. Position an absolute element at bottom right using position: 'absolute'.
jsx
import React from 'react';
import { View, Text } from 'react-native';
const AbsoluteBox = () => (
<View style={{ flex: 1 }}>
<Text style={{ position: 'absolute', bottom: 10, right: 10 }}>Bottom Right</Text>
</View>
);
export default AbsoluteBox;
33. Create a simple animation that fades in a view using Animated.
jsx
import React, { useEffect, useRef } from 'react';
import { Animated, View } from 'react-native';
const FadeIn = () => {
const fadeAnim = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(fadeAnim, { toValue: 1, duration: 1000, useNativeDriver: true }).start();
}, []);
return <Animated.View style={{ opacity: fadeAnim, width: 100, height: 100, backgroundColor: 'red' }} />;
};
export default FadeIn;
34. Use KeyboardAvoidingView to move the screen when keyboard appears.
jsx
import React from 'react';
import { KeyboardAvoidingView, TextInput, Platform } from 'react-native';
const AvoidKeyboard = () => (
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={{ flex: 1 }}>
<TextInput placeholder="Type here" style={{ marginTop: 400 }} />
</KeyboardAvoidingView>
);
export default AvoidKeyboard;
35. Implement a countdown timer using useState and useEffect with setInterval.
jsx
import React, { useState, useEffect } from 'react';
import { Text } from 'react-native';
const Countdown = ({ seconds }) => {
const [time, setTime] = useState(seconds);
useEffect(() => {
if (time <= 0) return;
const interval = setInterval(() => setTime(t => t - 1), 1000);
return () => clearInterval(interval);
}, [time]);
return <Text>Time left: {time}</Text>;
};
export default Countdown;
36. Use Picker from @react-native-picker/picker to select an option.
jsx
import React, { useState } from 'react';
import { Picker } from '@react-native-picker/picker';
const SelectExample = () => {
const [selected, setSelected] = useState('apple');
return (
<Picker selectedValue={selected} onValueChange={setSelected}>
<Picker.Item label="Apple" value="apple" />
<Picker.Item label="Banana" value="banana" />
</Picker>
);
};
export default SelectExample;
37. Create a component that uses useLayoutEffect to measure a view’s dimensions.
jsx
import React, { useLayoutEffect, useState } from 'react';
import { View, Text } from 'react-native';
const MeasureExample = () => {
const [width, setWidth] = useState(0);
useLayoutEffect(() => {
// measurement would require onLayout, but for demo:
// just set a value
setWidth(100);
}, []);
return <View><Text>Width: {width}</Text></View>;
};
export default MeasureExample;
38. Use FlatList with onEndReached to load more data (infinite scroll).
jsx
import React, { useState } from 'react';
import { FlatList, Text } from 'react-native';
const InfiniteScroll = () => {
const [items, setItems] = useState([...Array(20).keys()]);
const loadMore = () => setItems([...items, ...Array(10).keys()]);
return (
<FlatList
data={items}
renderItem={({ item }) => <Text>Item {item}</Text>}
onEndReached={loadMore}
onEndReachedThreshold={0.5}
/>
);
};
export default InfiniteScroll;
39. Use TouchableHighlight to show underlay color when pressed.
jsx
import React from 'react';
import { TouchableHighlight, Text } from 'react-native';
const HighlightButton = () => (
<TouchableHighlight underlayColor="lightgray" onPress={() => {}}>
<Text>Press me</Text>
</TouchableHighlight>
);
export default HighlightButton;
40. Use Clipboard from @react-native-clipboard/clipboard to copy text.
jsx
import React from 'react';
import { Button, Alert } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
const CopyText = () => {
const copy = () => {
Clipboard.setString('Hello');
Alert.alert('Copied!');
};
return <Button title="Copy" onPress={copy} />;
};
export default CopyText;
41. Display an image from a URL with a placeholder using Image props (onLoadStart, onLoadEnd).
jsx
import React, { useState } from 'react';
import { Image, ActivityIndicator } from 'react-native';
const RemoteImage = () => {
const [loading, setLoading] = useState(true);
return (
<>
{loading && <ActivityIndicator />}
<Image
source={{ uri: 'https://example.com/image.jpg' }}
onLoadStart={() => setLoading(true)}
onLoadEnd={() => setLoading(false)}
style={{ width: 100, height: 100 }}
/>
</>
);
};
export default RemoteImage;
42. Use React.memo to prevent unnecessary re-renders of a component.
jsx
import React, { useState } from 'react';
import { Text, Button } from 'react-native';
const Child = React.memo(({ count }) => <Text>Count: {count}</Text>);
const Parent = () => {
const [count, setCount] = useState(0);
return (
<>
<Child count={count} />
<Button title="Increment" onPress={() => setCount(c => c + 1)} />
</>
);
};
export default Parent;
43. Create a custom View that responds to touch movement using PanResponder.
jsx
import React, { useRef } from 'react';
import { PanResponder, View, Animated } from 'react-native';
const DraggableBox = () => {
const pan = useRef(new Animated.ValueXY()).current;
const panResponder = PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onPanResponderMove: Animated.event([null, { dx: pan.x, dy: pan.y }], { useNativeDriver: false }),
onPanResponderRelease: () => Animated.spring(pan, { toValue: { x: 0, y: 0 }, useNativeDriver: false }).start()
});
return (
<Animated.View style={{ transform: pan.getTranslateTransform(), width: 100, height: 100, backgroundColor: 'red' }} {...panResponder.panHandlers} />
);
};
export default DraggableBox;
44. Use Alert.prompt (iOS only) to get user input.
jsx
import { Alert, Button } from 'react-native';
const PromptExample = () => (
<Button title="Ask name" onPress={() => Alert.prompt('Enter name', undefined, text => console.log(text))} />
);
export default PromptExample;
45. Implement a simple useReducer example for a counter.
jsx
import React, { useReducer } from 'react';
import { Text, Button } from 'react-native';
const reducer = (state, action) => {
switch (action.type) {
case 'increment': return { count: state.count + 1 };
default: return state;
}
};
const CounterReducer = () => {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
<Text>{state.count}</Text>
<Button title="+" onPress={() => dispatch({ type: 'increment' })} />
</>
);
};
export default CounterReducer;
46. Use Platform.select to choose different styles per platform.
jsx
import React from 'react';
import { View, Text, Platform } from 'react-native';
const PlatformStyle = () => (
<View style={Platform.select({ ios: { backgroundColor: 'blue' }, android: { backgroundColor: 'green' } })}>
<Text>Platform specific style</Text>
</View>
);
export default PlatformStyle;
47. Create a component that uses BackHandler to handle Android back button.
jsx
import React, { useEffect } from 'react';
import { BackHandler, Alert } from 'react-native';
const BackHandlerExample = () => {
useEffect(() => {
const backAction = () => {
Alert.alert('Exit', 'Are you sure?', [{ text: 'Cancel', style: 'cancel' }, { text: 'OK', onPress: () => BackHandler.exitApp() }]);
return true;
};
const listener = BackHandler.addEventListener('hardwareBackPress', backAction);
return () => listener.remove();
}, []);
return null;
};
export default BackHandlerExample;
48. Use Linking to open phone dialer with a number.
jsx
import React from 'react';
import { Button, Linking } from 'react-native';
const CallButton = () => (
<Button title="Call" onPress={() => Linking.openURL('tel:1234567890')} />
);
export default CallButton;
Also try it: 100 kotlin practice problems with solutions
49. Create a SplashScreen that hides after 2 seconds using useEffect.
jsx
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
const Splash = ({ navigation }) => {
useEffect(() => {
setTimeout(() => navigation.replace('Home'), 2000);
}, []);
return (
<View><Text>Splash Screen</Text></View>
);
};
export default Splash;
50. Use InteractionManager to run code after interactions/animation complete.
jsx
import React, { useEffect } from 'react';
import { InteractionManager, Text } from 'react-native';
const AfterInteraction = () => {
useEffect(() => {
InteractionManager.runAfterInteractions(() => console.log('Interactions done'));
}, []);
return <Text>App is interactive</Text>;
};
export default AfterInteraction;
51. Use Vibration to trigger a short vibration.
jsx
import React from 'react';
import { Button, Vibration } from 'react-native';
const VibrateButton = () => (
<Button title="Vibrate" onPress={() => Vibration.vibrate(200)} />
);
export default VibrateButton;
52. Create a component that uses DeviceEventEmitter to listen to custom events (iOS/Android).
jsx
import React, { useEffect } from 'react';
import { DeviceEventEmitter } from 'react-native';
const EventListener = () => {
useEffect(() => {
const subscription = DeviceEventEmitter.addListener('customEvent', (data) => console.log(data));
return () => subscription.remove();
}, []);
return null;
};
export default EventListener;
53. Use PermissionsAndroid to request camera permission.
jsx
import React from 'react';
import { Button, PermissionsAndroid } from 'react-native';
const RequestCamera = async () => {
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA);
console.log(granted);
};
const CameraButton = () => <Button title="Request Camera" onPress={RequestCamera} />;
export default CameraButton;
54. Use Share to share text or url.
jsx
import React from 'react';
import { Button, Share } from 'react-native';
const ShareExample = () => {
const onShare = async () => {
await Share.share({ message: 'Check this out!' });
};
return <Button title="Share" onPress={onShare} />;
};
export default ShareExample;
55. Implement a Slider from @react-native-community/slider to change a value.
jsx
import React, { useState } from 'react';
import { Slider } from '@react-native-community/slider';
import { Text } from 'react-native';
const SliderExample = () => {
const [value, setValue] = useState(0.5);
return (
<>
<Slider value={value} onValueChange={setValue} />
<Text>Value: {value}</Text>
</>
);
};
export default SliderExample;
56. Use WebView from react-native-webview to load a website.
jsx
import React from 'react';
import { WebView } from 'react-native-webview';
const WebViewExample = () => <WebView source={{ uri: 'https://reactnative.dev' }} />;
export default WebViewExample;
57. Create a custom hook useDimensions that returns screen dimensions and updates on rotation.
jsx
import { useState, useEffect } from 'react';
import { Dimensions } from 'react-native';
const useDimensions = () => {
const [dimensions, setDimensions] = useState(Dimensions.get('window'));
useEffect(() => {
const subscription = Dimensions.addEventListener('change', ({ window }) => setDimensions(window));
return () => subscription?.remove();
}, []);
return dimensions;
};
// Usage in component
const ResponsiveBox = () => {
const { width } = useDimensions();
return <View style={{ width: width / 2, height: 50, backgroundColor: 'blue' }} />;
};
export default ResponsiveBox;
58. Use useImperativeHandle to expose a method to parent component.
jsx
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
import { Button } from 'react-native';
const Child = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
alertHello: () => alert('Hello'),
}));
return null;
});
const Parent = () => {
const childRef = useRef();
return <Button title="Call Child" onPress={() => childRef.current.alertHello()}><Child ref={childRef} /></Button>;
};
export default Parent;
59. Implement a simple network logger using XMLHttpRequest (to show response).
jsx
import React from 'react';
import { Button } from 'react-native';
const XHRExample = () => {
const load = () => {
const xhr = new XMLHttpRequest();
xhr.onload = () => console.log(xhr.responseText);
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1');
xhr.send();
};
return <Button title="Fetch with XHR" onPress={load} />;
};
export default XHRExample;
60. Use SectionList to display grouped data.
jsx
import React from 'react';
import { SectionList, Text } from 'react-native';
const sections = [{ title: 'Fruits', data: ['Apple', 'Banana'] }, { title: 'Vegetables', data: ['Carrot', 'Broccoli'] }];
const GroupedList = () => (
<SectionList
sections={sections}
renderItem={({ item }) => <Text>{item}</Text>}
renderSectionHeader={({ section }) => <Text style={{ fontWeight: 'bold' }}>{section.title}</Text>}
keyExtractor={(item, index) => index}
/>
);
export default GroupedList;
61. Create a component that uses AppState to detect when app goes to background.
jsx
import React, { useEffect } from 'react';
import { AppState, Text } from 'react-native';
const AppStateTracker = () => {
useEffect(() => {
const subscription = AppState.addEventListener('change', state => console.log('App state:', state));
return () => subscription.remove();
}, []);
return <Text>Check console</Text>;
};
export default AppStateTracker;
62. Use Keyboard to dismiss keyboard when tapping outside a TextInput.
jsx
import React from 'react';
import { Keyboard, TouchableWithoutFeedback, TextInput, View } from 'react-native';
const DismissKeyboard = () => (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={{ flex: 1 }}>
<TextInput placeholder="Tap outside to dismiss" />
</View>
</TouchableWithoutFeedback>
);
export default DismissKeyboard;
63. Use UIManager to measure a component’s position on screen.
jsx
import React, { useRef } from 'react';
import { UIManager, findNodeHandle, Text, Button } from 'react-native';
const MeasureComponent = () => {
const ref = useRef();
const measure = () => {
const node = findNodeHandle(ref.current);
UIManager.measure(node, (x, y, width, height, pageX, pageY) => console.log({ pageX, pageY }));
};
return (
<>
<Text ref={ref}>Measure me</Text>
<Button title="Measure" onPress={measure} />
</>
);
};
export default MeasureComponent;
64. Use NetInfo to check network connectivity.
jsx
import React, { useEffect, useState } from 'react';
import { Text } from 'react-native';
import NetInfo from '@react-native-community/netinfo';
const NetworkStatus = () => {
const [isConnected, setIsConnected] = useState(true);
useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => setIsConnected(state.isConnected));
return unsubscribe;
}, []);
return <Text>{isConnected ? 'Online' : 'Offline'}</Text>;
};
export default NetworkStatus;
65. Create a component that uses FlatList with sticky headers (using stickyHeaderIndices).
jsx
import React from 'react';
import { FlatList, Text } from 'react-native';
const data = ['Header', 'Item 1', 'Item 2'];
const StickyHeader = () => (
<FlatList data={data} stickyHeaderIndices={[0]} renderItem={({ item }) => <Text style={{ padding: 10 }}>{item}</Text>} />
);
export default StickyHeader;
66. Use TouchableNativeFeedback (Android only) for ripple effect.
jsx
import React from 'react';
import { TouchableNativeFeedback, Text } from 'react-native';
const RippleButton = () => (
<TouchableNativeFeedback onPress={() => {}}>
<Text style={{ padding: 10 }}>Ripple effect</Text>
</TouchableNativeFeedback>
);
export default RippleButton;
67. Implement a simple useInterval custom hook.
jsx
import { useEffect, useRef } from 'react';
const useInterval = (callback, delay) => {
const savedCallback = useRef();
useEffect(() => { savedCallback.current = callback; }, [callback]);
useEffect(() => {
if (delay !== null) {
const id = setInterval(() => savedCallback.current(), delay);
return () => clearInterval(id);
}
}, [delay]);
};
// Usage
const IntervalComponent = () => {
useInterval(() => console.log('tick'), 1000);
return null;
};
export default IntervalComponent;
68. Use ToastAndroid to show a toast on Android.
jsx
import React from 'react';
import { Button, ToastAndroid } from 'react-native';
const ToastExample = () => (
<Button title="Show Toast" onPress={() => ToastAndroid.show('Hello', ToastAndroid.SHORT)} />
);
export default ToastExample;
69. Implement a basic drawer navigation using @react-navigation/drawer.
jsx
import { NavigationContainer } from '@react-navigation/native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { Text } from 'react-native';
const Home = () => <Text>Home</Text>;
const Settings = () => <Text>Settings</Text>;
const Drawer = createDrawerNavigator();
export default () => (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Settings" component={Settings} />
</Drawer.Navigator>
</NavigationContainer>
);
70. Use useWindowDimensions to get reactive window dimensions.
jsx
import React from 'react';
import { useWindowDimensions, Text } from 'react-native';
const WindowInfo = () => {
const { width, height } = useWindowDimensions();
return <Text>Width: {width}, Height: {height}</Text>;
};
export default WindowInfo;
71. Use ImageBackground to overlay text on an image.
jsx
import React from 'react';
import { ImageBackground, Text } from 'react-native';
const BgImage = () => (
<ImageBackground source={require('./assets/bg.jpg')} style={{ width: 200, height: 100 }}>
<Text>Overlay text</Text>
</ImageBackground>
);
export default BgImage;
72. Create a component that uses Button with disabled prop to prevent multiple taps.
jsx
import React, { useState } from 'react';
import { Button } from 'react-native';
const DisableButton = () => {
const [disabled, setDisabled] = useState(false);
const handlePress = () => {
setDisabled(true);
setTimeout(() => setDisabled(false), 2000);
};
return <Button title="Press" onPress={handlePress} disabled={disabled} />;
};
export default DisableButton;
73. Use AccessibilityInfo to announce a message when something happens.
jsx
import React from 'react';
import { Button, AccessibilityInfo } from 'react-native';
const Announce = () => (
<Button title="Announce" onPress={() => AccessibilityInfo.announceForAccessibility('Button pressed')} />
);
export default Announce;
74. Use Easing from react-native-reanimated for custom animation curves.
jsx
import Animated, { Easing } from 'react-native-reanimated';
const { timing } = Animated;
// Example usage in component
const CustomEasing = () => {
const anim = new Animated.Value(0);
Animated.timing(anim, { toValue: 1, duration: 1000, easing: Easing.bounce, useNativeDriver: true }).start();
return <Animated.View style={{ opacity: anim, width: 100, height: 100, backgroundColor: 'red' }} />;
};
export default CustomEasing;
75. Create a component that uses FlatList with dynamic row height (automatic).
jsx
import React from 'react';
import { FlatList, Text, View } from 'react-native';
const data = [{ id: '1', text: 'short' }, { id: '2', text: 'very long text that wraps multiple lines' }];
const DynamicHeight = () => (
<FlatList data={data} renderItem={({ item }) => <View style={{ padding: 10 }}><Text>{item.text}</Text></View>} keyExtractor={item => item.id} />
);
export default DynamicHeight;
76. Implement a simple “like” button that toggles heart icon using FontAwesome from react-native-vector-icons.
jsx
import React, { useState } from 'react';
import { TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
const LikeButton = () => {
const [liked, setLiked] = useState(false);
return (
<TouchableOpacity onPress={() => setLiked(!liked)}>
<Icon name={liked ? 'heart' : 'heart-o'} size={30} color="red" />
</TouchableOpacity>
);
};
export default LikeButton;
77. Use CameraRoll from @react-native-community/cameraroll to save an image.
jsx
import { CameraRoll } from '@react-native-community/cameraroll';
const saveImage = async (uri) => {
await CameraRoll.save(uri, { type: 'photo' });
};
78. Use KeyboardAvoidingView with ScrollView to ensure input visible.
jsx
import React from 'react';
import { KeyboardAvoidingView, ScrollView, TextInput } from 'react-native';
const FormWithScroll = () => (
<KeyboardAvoidingView style={{ flex: 1 }} behavior="padding">
<ScrollView>
<TextInput placeholder="Field 1" />
<TextInput placeholder="Field 2" />
</ScrollView>
</KeyboardAvoidingView>
);
export default FormWithScroll;
79. Create a custom StatusBar component that changes style based on current screen (using navigation events).
jsx
import React, { useEffect } from 'react';
import { StatusBar } from 'react-native';
import { useNavigation } from '@react-navigation/native';
const DynamicStatusBar = ({ barStyle }) => {
const navigation = useNavigation();
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => StatusBar.setBarStyle(barStyle));
return unsubscribe;
}, [navigation, barStyle]);
return null;
};
// Usage: <DynamicStatusBar barStyle="light-content" />
export default DynamicStatusBar;
80. Implement a simple form validation for email and password fields.
jsx
import React, { useState } from 'react';
import { View, TextInput, Button, Alert } from 'react-native';
const ValidatedForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const validate = () => {
if (!email.includes('@')) return Alert.alert('Invalid email');
if (password.length < 6) return Alert.alert('Password too short');
Alert.alert('Success');
};
return (
<View>
<TextInput placeholder="Email" onChangeText={setEmail} />
<TextInput placeholder="Password" secureTextEntry onChangeText={setPassword} />
<Button title="Submit" onPress={validate} />
</View>
);
};
export default ValidatedForm;
81. Use Clipboard to read clipboard content.
jsx
import React from 'react';
import { Button, Alert } from 'react-native';
import Clipboard from '@react-native-clipboard/clipboard';
const ReadClipboard = () => {
const read = async () => {
const content = await Clipboard.getString();
Alert.alert('Clipboard', content);
};
return <Button title="Read Clipboard" onPress={read} />;
};
export default ReadClipboard;
Also try it: 100 Swift practice problems with solutions
82. Implement a component that uses useDebugValue to label custom hook in DevTools.
jsx
import { useDebugValue, useState } from 'react';
const useFriendStatus = (friendId) => {
const [isOnline, setIsOnline] = useState(false);
useDebugValue(isOnline ? 'Online' : 'Offline');
return isOnline;
};
// Usage in component
const FriendStatus = ({ id }) => {
const online = useFriendStatus(id);
return <Text>{online ? 'Online' : 'Offline'}</Text>;
};
83. Use InteractionManager to schedule a task after long list rendering.
jsx
import React, { useEffect, useState } from 'react';
import { InteractionManager, FlatList, Text } from 'react-native';
const HeavyList = () => {
const [ready, setReady] = useState(false);
useEffect(() => {
InteractionManager.runAfterInteractions(() => setReady(true));
}, []);
return ready ? <FlatList data={[...Array(100).keys()]} renderItem={({ item }) => <Text>{item}</Text>} /> : <Text>Loading...</Text>;
};
export default HeavyList;
84. Use LayoutAnimation to animate layout changes (simple expand/collapse).
jsx
import React, { useState } from 'react';
import { LayoutAnimation, View, Button } from 'react-native';
const ExpandCollapse = () => {
const [expanded, setExpanded] = useState(false);
const toggle = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setExpanded(!expanded);
};
return (
<View>
<Button title="Toggle" onPress={toggle} />
{expanded && <View style={{ height: 100, backgroundColor: 'blue' }} />}
</View>
);
};
export default ExpandCollapse;
85. Create a component that uses Image with resizeMode cover.
jsx
import React from 'react';
import { Image } from 'react-native';
const CoverImage = () => (
<Image source={{ uri: 'https://picsum.photos/200/300' }} style={{ width: 200, height: 200 }} resizeMode="cover" />
);
export default CoverImage;
86. Use PixelRatio to get device pixel ratio.
jsx
import React from 'react';
import { PixelRatio, Text } from 'react-native';
const PixelInfo = () => <Text>Pixel ratio: {PixelRatio.get()}</Text>;
export default PixelInfo;
87. Implement a simple usePrevious hook to track previous value.
jsx
import { useRef, useEffect } from 'react';
const usePrevious = (value) => {
const ref = useRef();
useEffect(() => { ref.current = value; }, [value]);
return ref.current;
};
// Usage
const PreviousExample = ({ count }) => {
const prevCount = usePrevious(count);
return <Text>Current: {count}, Previous: {prevCount}</Text>;
};
export default PreviousExample;
88. Use Platform.select to import different modules per platform.
jsx
const Component = Platform.select({
ios: () => require('./iOSComponent').default,
android: () => require('./AndroidComponent').default,
})();
export default Component;
89. Create a custom View that detects touch location using onStartShouldSetResponder.
jsx
import React from 'react';
import { View, Text } from 'react-native';
const TouchDetector = () => {
const onTouch = (evt) => console.log('Touch at:', evt.nativeEvent.locationX);
return (
<View
onStartShouldSetResponder={() => true}
onResponderGrant={onTouch}
style={{ width: 200, height: 200, backgroundColor: 'yellow' }}
>
<Text>Touch anywhere</Text>
</View>
);
};
90. Use useScrollToTop from @react-navigation/native to scroll to top when tapping active tab.
jsx
import React, { useRef } from 'react';
import { useScrollToTop } from '@react-navigation/native';
import { FlatList } from 'react-native';
const ScrollableScreen = () => {
const ref = useRef(null);
useScrollToTop(ref);
return <FlatList ref={ref} data={[...Array(100).keys()]} renderItem={({ item }) => <Text>{item}</Text>} />;
};
export default ScrollableScreen;
91. Use ActionSheetIOS to show an action sheet on iOS.
jsx
import { ActionSheetIOS, Button } from 'react-native';
const ActionSheetExample = () => (
<Button title="Show Action Sheet" onPress={() => ActionSheetIOS.showActionSheetWithOptions({ options: ['Option1', 'Cancel'], cancelButtonIndex: 1 }, (idx) => console.log(idx))} />
);
export default ActionSheetExample;
92. Implement a simple deep link handler using Linking event listener.
jsx
import React, { useEffect } from 'react';
import { Linking } from 'react-native';
const DeepLinkHandler = () => {
useEffect(() => {
const handleUrl = ({ url }) => console.log('Received url:', url);
Linking.addEventListener('url', handleUrl);
return () => Linking.removeEventListener('url', handleUrl);
}, []);
return null;
};
export default DeepLinkHandler;
93. Use Keyboard.dismiss with ScrollView prop keyboardShouldPersistTaps="handled".
jsx
import React from 'react';
import { Keyboard, ScrollView, TextInput, TouchableWithoutFeedback } from 'react-native';
const DismissScroll = () => (
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView keyboardShouldPersistTaps="handled">
<TextInput />
<TextInput />
</ScrollView>
</TouchableWithoutFeedback>
);
export default DismissScroll;
94. Use Pressable for advanced press states (hover, pressed).
jsx
import React from 'react';
import { Pressable, Text } from 'react-native';
const PressableExample = () => (
<Pressable onPress={() => {}} style={({ pressed }) => ({ opacity: pressed ? 0.5 : 1 })}>
<Text>Press me</Text>
</Pressable>
);
export default PressableExample;
95. Use refreshControl inside ScrollView (not just FlatList).
jsx
import React, { useState } from 'react';
import { ScrollView, RefreshControl, Text } from 'react-native';
const ScrollRefresh = () => {
const [refreshing, setRefreshing] = useState(false);
const onRefresh = () => {
setRefreshing(true);
setTimeout(() => setRefreshing(false), 1000);
};
return (
<ScrollView refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}>
<Text>Pull to refresh</Text>
</ScrollView>
);
};
export default ScrollRefresh;
96. Create a component that uses FlatList with getItemLayout for performance.
jsx
import React from 'react';
import { FlatList, Text } from 'react-native';
const data = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
const OptimizedList = () => (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item}</Text>}
getItemLayout={(data, index) => ({ length: 40, offset: 40 * index, index })}
/>
);
export default OptimizedList;
97. Use InAppBrowser from react-native-inappbrowser-reborn to open a URL in app.
jsx
import { InAppBrowser } from 'react-native-inappbrowser-reborn';
const openUrl = async (url) => {
if (await InAppBrowser.isAvailable()) {
await InAppBrowser.open(url);
}
};
98. Use BackgroundTimer from react-native-background-timer to run periodic tasks in background.
jsx
import BackgroundTimer from 'react-native-background-timer';
BackgroundTimer.setTimeout(() => console.log('Background task'), 1000);
99. Implement a component that uses React.forwardRef to forward a ref to a child TextInput.
jsx
import React, { useRef } from 'react';
import { TextInput, Button } from 'react-native';
const FancyInput = React.forwardRef((props, ref) => <TextInput ref={ref} {...props} />);
const ParentComponent = () => {
const inputRef = useRef();
return (
<>
<FancyInput ref={inputRef} placeholder="Focus me" />
<Button title="Focus" onPress={() => inputRef.current.focus()} />
</>
);
};
export default ParentComponent;
100. Use _ (lodash) debounce to prevent rapid button presses.
jsx
import React, { useCallback } from 'react';
import { Button } from 'react-native';
import debounce from 'lodash/debounce';
const DebouncedButton = () => {
const handlePress = useCallback(debounce(() => console.log('Pressed'), 500), []);
return <Button title="Press me" onPress={handlePress} />;
};
export default DebouncedButton;
Also try it: 100 C++ practice problems with solutions
Final Thought
One hundred problems. One hundred tiny battles with a blank screen, a cryptic red error, or a component that just refused to render. And you know what? You didn’t throw your laptop out the window — even if you wanted to. There’s a fire in you that’s part fury and part fierce, stubborn love. Love for the craft.
Love for that moment when the UI finally, beautifully, just works. And maybe a little anger too — anger at all the times you were made to feel “not technical enough,” anger at imposter syndrome hissing lies, anger that once fueled your focus until the bug was dead and the screen glowed with your own creation.
Use that fire. It’s not a weakness; it’s proof you care deeply. Keep building with love, keep debugging with that fire in your belly, and never let the grind steal the joy that made you open this post in the first place. The apps you’re going to build will matter — because you built them with both passion and persistence. Now go make something wonderful.