Skip to main content

10 React Native Tips & Tricks to Level Up Your Development

 React Native is a powerful framework, but even experienced developers can benefit from lesser-known tips that boost workflow and app quality. This guide shares 10 practical React Native tips – from keyboard management to platform-specific styling – designed to enhance your development skills and create more polished, efficient applications.


1. Mastering Keyboard Dismissal in Lists: A Seamless User Experience

When building applications that heavily rely on lists with input fields, effectively managing the keyboard becomes paramount. A common frustration for users is having the keyboard obscure content when they're trying to navigate the list. React Native offers a simple yet powerful solution through the keyboardDismissMode prop of the FlatList component.


The keyboardDismissMode Prop: 

By setting the keyboardDismissMode prop to "on-drag", you instruct the FlatList to automatically dismiss the keyboard when the user initiates a drag gesture on the list. This eliminates the need for manual keyboard dismissal and provides a more seamless user experience.



import React from 'react'; import { FlatList, TextInput, View, StyleSheet } from 'react-native'; const data = Array.from({ length: 20 }, (_, i) => ({ id: i.toString(), text: `Item ${i + 1}` })); const KeyboardDismissList = () => { return ( <FlatList data={data} renderItem={({ item }) => ( <View style={styles.item}> <TextInput style={styles.input} placeholder={`Enter text for ${item.text}`} /> </View> )} keyExtractor={item => item.id} keyboardDismissMode="on-drag" /> ); }; const styles = StyleSheet.create({ item: { padding: 10, borderBottomWidth: 1, borderBottomColor: '#ddd', }, input: { height: 40, borderColor: 'gray', borderWidth: 1, paddingHorizontal: 10, }, }); export default KeyboardDismissList;


Elevated UI with Animated Lists:

 For an enhanced user interface, consider integrating React Native Reanimated to create animated list transitions. By using Animated.FlatList and ItemLayoutAnimation, you can add smooth animations when items are added or removed from the list, making the application feel more responsive and polished.



import React from 'react'; import Animated, { useAnimatedStyle, useSharedValue, withTiming, LayoutAnimation } from 'react-native-reanimated'; import { FlatList, TextInput, View, StyleSheet } from 'react-native'; const data = Array.from({ length: 20 }, (_, i) => ({ id: i.toString(), text: `Item ${i + 1}` })); const AnimatedKeyboardDismissList = () => { const animatedStyle = useAnimatedStyle(() => { return { opacity: withTiming(1, { duration: 500 }), // Example animation }; }); return ( <Animated.FlatList data={data} renderItem={({ item }) => ( <Animated.View style={[styles.item, animatedStyle]}> <TextInput style={styles.input} placeholder={`Enter text for ${item.text}`} /> </Animated.View> )} keyExtractor={item => item.id} keyboardDismissMode="on-drag" ItemLayoutAnimation={LayoutAnimation.Presets.spring} /> ); }; const styles = StyleSheet.create({ item: { padding: 10, borderBottomWidth: 1, borderBottomColor: '#ddd', }, input: { height: 40, borderColor: 'gray', borderWidth: 1, paddingHorizontal: 10, }, }); export default AnimatedKeyboardDismissList;


2. Harnessing the Power of Pressable: Fine-Grained Control Over Touch Events

While TouchableOpacity is a common choice for creating interactive elements, the Pressable component offers a more robust and future-proof approach to handling touch-based inputs. Pressable provides granular control over different press states, allowing you to customize the appearance and behavior of your components based on user interactions.


Diving into Press States: 

The Pressable component exposes events such as onPressIn and onPressOut, which enable you to precisely track and respond to different phases of a press event. This is particularly useful for creating visual feedback that enhances the user experience.



import React, { useState } from 'react'; import { Pressable, Text, StyleSheet } from 'react-native'; const CustomButton = () => { const [isPressed, setIsPressed] = useState(false); return ( <Pressable onPressIn={() => setIsPressed(true)} onPressOut={() => setIsPressed(false)} style={({ pressed }) => [ styles.button, { backgroundColor: pressed ? 'darkblue' : 'royalblue' }, ]} > <Text style={styles.text}> {isPressed ? 'Pressed!' : 'Press Me'} </Text> </Pressable> ); }; const styles = StyleSheet.create({ button: { paddingVertical: 12, paddingHorizontal: 32, borderRadius: 4, elevation: 3, }, text: { fontSize: 16, lineHeight: 21, fontWeight: 'bold', letterSpacing: 0.25, color: 'white', }, }); export default CustomButton;


3. Embracing Dark Mode with React Navigation Theme Provider

Dark mode has become an essential feature for modern applications, providing users with a more comfortable viewing experience in low-light conditions. Implementing dark mode in React Native is made easier with the help of React Navigation's ThemeProvider component.


Seamless Theme Switching:

 By wrapping your application with ThemeProvider, you can define both default and dark themes and automatically style your components based on the user's system preference. This eliminates the need for manual theme management and ensures a consistent user experience across the entire application.


Leveraging useColorScheme

The useColorScheme hook from React Native allows you to detect the user's system-wide color scheme preference. You can then use this information to dynamically switch between your light and dark themes.



import React from 'react'; import { AppearanceProvider, useColorScheme } from 'react-native-appearance'; import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native'; import MyNavigator from './MyNavigator'; // Your navigator component const App = () => { const scheme = useColorScheme(); return ( <AppearanceProvider> <NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}> <MyNavigator /> </NavigationContainer> </AppearanceProvider> ); }; export default App;


4. Platform Specific Styling with Platform.select

Different platforms sometimes require different styling to achieve the desired look and feel.


You can use Platform.select to specify different styles for iOS and Android (and even other platforms like web, macOS, and Windows).

PlatformColor allows you to use the system's native colors, giving your app a truly native feel.



import { StyleSheet, Platform, View, Text } from 'react-native'; const styles = StyleSheet.create({ container: { padding: 20, }, button: { backgroundColor: Platform.select({ ios: 'blue', android: 'green', }), padding: 10, borderRadius: 5, }, buttonText: { color: Platform.select({ ios: 'white', android: 'black', }), textAlign: 'center', }, nativeText: { color: Platform.select({ ios: PlatformColor('labelColor'), android: PlatformColor('textColor'), }), } }); const PlatformStyling = () => { return ( <View style={styles.container}> <View style={styles.button}> <Text style={styles.buttonText}>Platform Specific Button</Text> </View> <Text style={styles.nativeText}>Native Text Color</Text> </View> ); }; export default PlatformStyling;


5. Using Google Fonts with Expo

Adding custom fonts to your app can greatly enhance its visual appeal. With Expo, using Google Fonts is incredibly simple.

  • Install the @expo-google-fonts/* package for the specific fonts you want to use.
  • Use the useFonts hook to load the fonts, and then apply them to your text elements.



import React from 'react'; import { Text, View, StyleSheet } from 'react-native'; import { useFonts, Raleway_400Regular, Raleway_700Bold } from '@expo-google-fonts/raleway'; const FontExample = () => { let [fontsLoaded] = useFonts({ Raleway_400Regular, Raleway_700Bold, }); if (!fontsLoaded) { return <View><Text>Loading...</Text></View>; } return ( <View style={styles.container}> <Text style={{ fontFamily: 'Raleway_400Regular', fontSize: 20 }}> Raleway Regular </Text> <Text style={{ fontFamily: 'Raleway_700Bold', fontSize: 20 }}> Raleway Bold </Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); export default FontExample;


6. Image Loading Optimization

Optimize image loading by using the defaultSource prop in the Image component.


This allows you to display a placeholder image while the actual image is loading from the network, improving the user experience.



import React from 'react'; import { Image, View, StyleSheet } from 'react-native'; const ImageLoading = () => { return ( <View style={styles.container}> <Image style={styles.image} source={{ uri: 'https://via.placeholder.com/400', // Replace with a large image URL }} defaultSource={require('./assets/placeholder.png')} // Replace with a local placeholder image /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, image: { width: 200, height: 200, }, }); export default ImageLoading;


7. Text Element Optimization

Improve the rendering of long text strings using numberOfLines and adjustFontSizeToFit.

  • numberOfLines limits the number of lines displayed, adding ellipsis at the end.
  • adjustFontSizeToFit automatically scales down the font size to fit within the available space.



import React from 'react'; import { Text, View, StyleSheet } from 'react-native'; const LongTextExample = () => { const longText = `This is a very long text string that might not fit in the available space. We can use numberOfLines to limit the number of lines displayed and add an ellipsis at the end. Alternatively, we can use adjustFontSizeToFit to automatically scale down the font size to fit within the available space.`; return ( <View style={styles.container}> <Text style={styles.text} numberOfLines={3}> {longText} </Text> <Text style={styles.text} adjustFontSizeToFit numberOfLines={3}> {longText} </Text> </View> ); }; const styles = StyleSheet.create({ container: { padding: 20, }, text: { fontSize: 16, lineHeight: 24, }, }); export default LongTextExample;


8. Managing Warnings with LogBox

Use LogBox to ignore specific warnings that are not relevant or cannot be immediately fixed.

  • This can help keep your console clean and focused on important issues.
  • Be cautious when using ignoreAllLogs as it might hide critical warnings.


import { LogBox, View, Text } from 'react-native'; import React, { useEffect } from 'react'; const WarningExample = () => { useEffect(() => { LogBox.ignoreLogs(['Some non-critical warning']); // Ignore specific warning }, []); return ( <View> <Text>Check the console (some warnings might be hidden)</Text> </View> ); }; export default WarningExample;


9. Handling Local API URLs on Android

When testing your React Native app on an Android emulator, localhost does not resolve to your development machine.

  • Use 10.0.2.2 instead of localhost to access your local API server.
  • You can also use ADB to map ports.



import { Platform } from 'react-native'; const API_URL = Platform.OS === 'android' ? 'http://10.0.2.2:8080/api' : 'http://localhost:8080/api'; const fetchData = async () => { try { const response = await fetch(API_URL + '/data'); const data = await response.json(); console.log('Data:', data); } catch (error) { console.error('Error fetching data:', error); } }; export default fetchData;


10. Building Production Apps with Expo

To build a standalone app with Expo:

Prebuild your app with Expo.

In Xcode, edit the scheme and set the build configuration to "Release."

In Android Studio, change the build variant to "Release" and build the APK.


Conclusion: Continuously Learning and Improving

React Native is an ever-evolving framework, and staying up-to-date with the latest tips and tricks is crucial for building high-quality applications. By incorporating these 10 practical tips into your development workflow, you can significantly improve your productivity, enhance the user experience, and create more polished and efficient React Native applications. Remember to always explore new techniques, experiment with different approaches to foster continuous learning & innovation.

Comments

Topics

Show more