Mobile Apps (React Native)

Performance, Accessibility and Polish

35 min

Users judge mobile apps in seconds. Jank, tiny tap targets and broken dark mode feel unprofessional even if the features work.

Keep the UI thread free

React Native runs your JavaScript on one thread and the native UI on another. Heavy work in JavaScript (big loops, parsing huge JSON) delays touches and animations.

  • Move expensive calculations out of render; memoise with useMemo when profiling shows a cost.
  • Paginate and filter on the server instead of shipping thousands of rows.
  • Use Reanimated for animations: they run on the UI thread and stay smooth even when JavaScript is busy.
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";

function PressableCard({ children }) {
  const scale = useSharedValue(1);
  const style = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }] }));
  return (
    <Pressable onPressIn={() => (scale.value = withSpring(0.97))}
               onPressOut={() => (scale.value = withSpring(1))}>
      <Animated.View style={style}>{children}</Animated.View>
    </Pressable>
  );
}

Fast lists and images

  • Give FlatList a stable keyExtractor, memoise row components (React.memo) and set getItemLayout when rows have a fixed height.
  • FlashList (by Shopify) is a drop-in replacement that is faster for long, complex lists.
  • Use expo-image for caching, placeholders and modern formats; request appropriately sized images from your server.

Accessibility

<Pressable
  accessibilityRole="button"
  accessibilityLabel="Add Python Programming to my tracks"
  hitSlop={8}
  onPress={add}>
  <Ionicons name="add-circle" size={28} />
</Pressable>
  • Every icon-only control needs an accessibilityLabel.
  • Tap targets of at least about 44×44 points (use hitSlop for small icons).
  • Respect the user's font size: avoid fixed heights on text containers so larger system fonts do not get cut off.
  • Test with VoiceOver (iOS) and TalkBack (Android) at least once per release.

Dark mode and theming

import { useColorScheme } from "react-native";
const scheme = useColorScheme();               // "light" | "dark"
const colors = scheme === "dark" ? darkTheme : lightTheme;

Define colour tokens once and read them everywhere, like CSS variables on the web. Check contrast in both themes.

Polish that matters

  • Loading skeletons instead of blank screens; empty states with a helpful next action.
  • Haptic feedback for important actions (expo-haptics), used sparingly.
  • Consistent spacing scale and typography.
  • Handle the Android back button and edge-to-edge layouts correctly.

Test on real devices

Simulators hide real-world problems. Test on at least one older Android phone and one iPhone, on a slow network (developer settings can throttle), with large text and with the screen reader on.

Exercise

Audit your app: add accessibility labels to every icon button, increase small tap targets, switch the tracks list to FlashList with memoised rows, add a pressed-scale animation with Reanimated, and verify both colour schemes on a real device.

Check yourself

  • Why do Reanimated animations stay smooth when JavaScript is busy?
  • What does an icon-only button need for screen readers?
  • Why test with large system fonts?

I tuoi progressi sono salvati solo in questo browser.

Invia per la revisione (10 punti)