In React Native 0.87, what can the StatusBar component still control, and why were its backgroundColor and translucent props removed?
answer
- icons and visibility only
- 'default' differs per platform
- edge-to-edge made colour meaningless
- removed in 0.87 with their setters
- mounted bars merge like a stack
basics
~20 sIn React Native 0.87, StatusBar controls barStyle (icon colour), hidden, animated and the iOS showHideTransition. backgroundColor, translucent and networkActivityIndicatorVisible were removed because Android now draws apps edge to edge, so a status bar colour has no effect.
solid answer
~40 s`StatusBar` now configures only the content of the system bar: `barStyle` (`'default'`, `'auto'`, `'light-content'`, `'dark-content'`), `hidden`, `animated` for those two, and iOS `showHideTransition`. Note that `'default'` is light content on Android but dark on iOS. React Native 0.87 removed the deprecated `backgroundColor`, `translucent` and `networkActivityIndicatorVisible` props and their setters. Android 15 draws apps targeting API 35 edge to edge, Android 16 (the default target since 0.81) removes the opt-out, and with the app always behind the bar, bar colour and translucency stopped doing anything. Instead, paint your own `View` under the bar using the safe-area insets and pick a contrasting `barStyle`. Several mounted `StatusBar` components merge in mount order, and Expo SDK 57 (0.86) still has the props, deprecated.
code
tsx · 12 linesimport {StatusBar, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
export function PhotoViewerHeader() {
const insets = useSafeAreaInsets();
return (
<>
<StatusBar barStyle="light-content" animated />
<View style={{height: insets.top, backgroundColor: '#000000'}} />
</>
);
}go deeper
Recall the props that remain in 0.87, barStyle, hidden and animated, and that backgroundColor and translucent are gone.
Explain the removal through Android edge-to-edge (forced for API 35 targets, no opt-out on Android 16), the per-platform meaning of 'default', and how mounted StatusBars merge.
Upgrade code that set status bar colours by drawing an inset-sized View and choosing barStyle per screen, and avoid mixing imperative calls with mounted components.
Own the upgrade path: audit status-bar and inset handling before moving past 0.86, and set one per-screen pattern so edge-to-edge regressions do not reappear.
## What StatusBar is for React Native's `StatusBar` component (from `react-native`) configures the system status bar: the strip at the top with the clock, network and battery icons. It renders nothing itself; mounting it sends settings to the OS. Over the last few releases its job has **shrunk**, and interviewers use that to check whether a candidate's knowledge is current. ## What it still controls in 0.87 | Prop | Values | Notes | |---|---|---| | `barStyle` | `'default'`, `'auto'`, `'light-content'`, `'dark-content'` | colour of the status bar's text and icons | | `hidden` | boolean, default `false` | hides or shows the bar | | `animated` | boolean, default `false` | animates `barStyle` and `hidden` changes | | `showHideTransition` (iOS) | `'fade'` (default), `'slide'`, `'none'` | transition used for `hidden` | Details worth knowing: - **`'default'`** means light content on Android and dark content on iOS, so the same app can have light icons on one platform and dark icons on the other. - **`'auto'`** picks `light-content` or `dark-content` from the current colour scheme and follows changes to it. It appears in the 0.87 docs and not in the 0.86 ones. - **`StatusBar.currentHeight`** is an Android-only constant for the bar's height. - **Static methods** (`setBarStyle`, `setHidden`, and `pushStackEntry` / `popStackEntry` / `replaceStackEntry`) exist for imperative use. The docs warn that a value set by the static API is overridden by a mounted component on its next render, so do not mix the two for the same prop. ## What was removed, and why React Native 0.87 removed the deprecated **`backgroundColor`**, **`translucent`** and **`networkActivityIndicatorVisible`** props, along with their setter methods. The first two died because of **edge-to-edge on Android**: 1. Apps targeting Android 15 (API 35) are drawn edge to edge by the OS, so content extends behind the status bar. 2. Android 16 removes the opt-out, and it has been React Native's default target since 0.81. 3. With the app always drawn behind the bar, setting its background colour or translucency stopped having any effect. The 0.86 docs already warned that both were deprecated and ineffective at API 35. The replacement is ordinary layout. Draw your own coloured `View` in the top area, sized by the safe-area insets, and choose a `barStyle` that contrasts with it. (Computing those insets is a keyboard-and-safe-area topic in its own right.) Version note: Expo SDK 57 runs React Native 0.86, where the core props still exist but are deprecated and have no effect on edge-to-edge Android. `expo-status-bar` dropped them in SDK 56. ## Several StatusBars at once It is normal to mount a `StatusBar` per screen, for example `light-content` over the dark photo viewer and `dark-content` on the white settings screen. React Native keeps a **stack**: the props of all mounted `StatusBar` components are **merged in the order they were mounted**, with later values overriding earlier ones for the props they set. Unmounting a screen pops its entry, so the previous style returns. The imperative `pushStackEntry` and `popStackEntry` expose the same mechanism. Since React Native 0.86, status bar settings also apply while a `Modal` is open, which fixed mismatched icons over full-screen modals. ## Choosing barStyle per screen With edge-to-edge, the colour behind the status bar is whatever your screen draws there, so `barStyle` has to follow each screen's own top colour: - A **dark header or full-bleed photo** needs `light-content`. - A **white or light background** needs `dark-content`. - A screen that **follows the system theme** can use `'auto'` in 0.87, or choose explicitly from the current colour scheme in earlier versions. - A **full-screen viewer** may set `hidden`, with `animated` so that showing and hiding does not jump. Mounting a `StatusBar` element inside each screen keeps the choice next to the layout that motivates it, and the stack restores the previous screen's style when you navigate back. ## Common mistakes - Setting `backgroundColor` and expecting a coloured bar. In 0.87 the prop no longer exists. - Relying on `'default'` and getting light icons on a white Android screen. - Mixing `StatusBar.setBarStyle(...)` with a mounted `<StatusBar barStyle>`, so the component silently overwrites the imperative call. - Hiding the bar on one screen and forgetting that the stack restores the previous state only when that screen's `StatusBar` unmounts.
- Two React Native screens each mount a StatusBar with different barStyle values. Which one wins?Both stay on a stack, and their props are merged in mount order, so the later-mounted screen's `barStyle` wins while it is mounted. When it unmounts, its entry is popped and the earlier screen's style returns. Props the later one does not set keep the earlier values.
- Why can StatusBar.setBarStyle appear not to work in a React Native app?If a `<StatusBar>` component is mounted and sets `barStyle`, it overrides the imperative value on its next render. The docs recommend not mixing the static API and the component for the same prop. Pick one approach per prop.
saying these in an interview costs you the question
- StatusBar backgroundColor is the way to colour the Android status bar in 0.87.
- barStyle 'default' gives dark icons on both platforms.
- Only one StatusBar component may be mounted at a time.
- translucent is still needed to draw content behind the Android status bar.
- Imperative StatusBar calls always override a mounted StatusBar component.