React Native 0.86 em 2026: Edge-to-Edge Android, DevTools e Perguntas de Entrevista
Domine o React Native 0.86 com suporte edge-to-edge para Android 15+, melhorias no DevTools e perguntas práticas de entrevista. Guia completo com exemplos de código.

O React Native 0.86 introduz suporte completo edge-to-edge para Android 15+, sendo a segunda versão consecutiva sem mudanças que quebram compatibilidade. Lançada em junho de 2026, esta versão corrige as APIs críticas de layout e medição que a aplicação obrigatória do edge-to-edge no Android estava quebrando silenciosamente.
O React Native 0.86 mantém compatibilidade total com a versão 0.85. A atualização não requer modificações de código para a maioria das aplicações, tornando-a uma das transições de versão mais suaves na história do React Native.
Entendendo Edge-to-Edge no Android 15
Os layouts edge-to-edge permitem que o conteúdo se estenda sob os elementos de interface do sistema, como a barra de status e a barra de navegação. O Android 15 impõe esse comportamento por padrão, independentemente da configuração do aplicativo. O React Native 0.86 garante que todas as APIs de medição e layout funcionem corretamente nessas condições.
A função measureInWindow agora retorna coordenadas precisas quando o modo edge-to-edge está ativo. Anteriormente, as medições podiam estar deslocadas pela altura dos elementos de interface do sistema, causando bugs de posicionamento em overlays, tooltips e botões de ação flutuantes.
import React, { useRef, useCallback } from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
interface TooltipPosition {
x: number;
y: number;
}
export function SafeAreaHandler() {
const buttonRef = useRef<View>(null);
const insets = useSafeAreaInsets();
const showTooltip = useCallback(() => {
// measureInWindow now returns correct coordinates on Android 15+
buttonRef.current?.measureInWindow((x, y, width, height) => {
const position: TooltipPosition = {
x: x + width / 2,
// Coordinates are accurate even with edge-to-edge enabled
y: y + height + 8,
};
console.log('Tooltip position:', position);
});
}, []);
return (
<View style={[styles.container, { paddingTop: insets.top }]}>
<View ref={buttonRef} collapsable={false}>
<TouchableOpacity onPress={showTooltip} style={styles.button}>
<Text style={styles.buttonText}>Show Tooltip</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
button: { backgroundColor: '#007AFF', padding: 16, borderRadius: 8 },
buttonText: { color: '#FFFFFF', fontWeight: '600' },
});A prop collapsable={false} garante que a View mantenha uma referência nativa para medições. Sem isso, o React Native pode otimizar a view nativa, fazendo com que measureInWindow falhe.
Correções do KeyboardAvoidingView para Android 15
O componente KeyboardAvoidingView calculava incorretamente o espaço disponível quando o modo edge-to-edge está ativo. A versão 0.86 corrige isso levando em conta os insets de interface do sistema no cálculo da altura disponível.
import React, { useState } from 'react';
import {
KeyboardAvoidingView,
TextInput,
Platform,
StyleSheet,
View,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export function ChatInput() {
const [message, setMessage] = useState('');
const insets = useSafeAreaInsets();
return (
<KeyboardAvoidingView
// behavior="padding" works correctly on Android 15+ edge-to-edge
behavior={Platform.OS === 'ios' ? 'padding' : 'padding'}
style={styles.container}
// keyboardVerticalOffset accounts for headers and safe areas
keyboardVerticalOffset={Platform.select({ ios: 88, android: 0 })}
>
<View style={styles.content}>
{/* Chat messages would render here */}
</View>
<View style={[styles.inputContainer, { paddingBottom: insets.bottom }]}>
<TextInput
value={message}
onChangeText={setMessage}
placeholder="Type a message..."
style={styles.input}
multiline
/>
</View>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
content: { flex: 1 },
inputContainer: { borderTopWidth: 1, borderTopColor: '#E5E5E5', padding: 8 },
input: { minHeight: 40, padding: 12, backgroundColor: '#F5F5F5', borderRadius: 20 },
});No Android 15, usar behavior="height" frequentemente causa saltos de layout. O behavior padding fornece animações mais suaves e posicionamento mais previsível com edge-to-edge habilitado.
Atualizações da StatusBar Durante a Exibição de Modais
Um bug persistente impedia alterações de estilo e visibilidade da StatusBar enquanto um Modal estava aberto. O React Native 0.86 resolve isso, permitindo theming dinâmico da barra de status em fluxos modais.
import React, { useState, useEffect } from 'react';
import { Modal, View, StatusBar, Text, Pressable, StyleSheet } from 'react-native';
interface ThemedModalProps {
visible: boolean;
onClose: () => void;
darkMode?: boolean;
}
export function ThemedModal({ visible, onClose, darkMode = false }: ThemedModalProps) {
// StatusBar changes now apply correctly while modal is visible
useEffect(() => {
if (visible) {
StatusBar.setBarStyle(darkMode ? 'light-content' : 'dark-content', true);
StatusBar.setBackgroundColor(darkMode ? '#1A1A1A' : '#FFFFFF', true);
}
return () => {
// Restore original status bar when modal closes
StatusBar.setBarStyle('dark-content', true);
StatusBar.setBackgroundColor('#FFFFFF', true);
};
}, [visible, darkMode]);
return (
<Modal visible={visible} animationType="slide" onRequestClose={onClose}>
<View style={[styles.modalContent, darkMode && styles.darkBackground]}>
<StatusBar
barStyle={darkMode ? 'light-content' : 'dark-content'}
backgroundColor={darkMode ? '#1A1A1A' : '#FFFFFF'}
/>
<Text style={[styles.title, darkMode && styles.lightText]}>
Modal Content
</Text>
<Pressable onPress={onClose} style={styles.closeButton}>
<Text style={styles.closeButtonText}>Close</Text>
</Pressable>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
modalContent: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFFFFF' },
darkBackground: { backgroundColor: '#1A1A1A' },
title: { fontSize: 24, fontWeight: 'bold', color: '#000000' },
lightText: { color: '#FFFFFF' },
closeButton: { marginTop: 20, padding: 12, backgroundColor: '#007AFF', borderRadius: 8 },
closeButtonText: { color: '#FFFFFF', fontWeight: '600' },
});Essa correção é particularmente importante para aplicações que implementam alternadores de modo escuro em fluxos modais, como telas de configurações ou visualizadores de imagens.
Pronto para mandar bem nas entrevistas de React Native?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Emulação de Modo Claro e Escuro no DevTools
O React Native DevTools introduz suporte para Emulation.setEmulatedMedia, permitindo troca instantânea de tema sem modificar a configuração do dispositivo ou emulador. Essa funcionalidade é acessada através da Paleta de Comandos com Cmd+Shift+P (macOS) ou Ctrl+Shift+P (Windows/Linux).
import React, { createContext, useContext, useState, useEffect } from 'react';
import { useColorScheme, Appearance } from 'react-native';
type Theme = 'light' | 'dark';
interface ThemeContextValue {
theme: Theme;
toggleTheme: () => void;
colors: typeof lightColors;
}
const lightColors = {
background: '#FFFFFF',
surface: '#F5F5F5',
text: '#000000',
textSecondary: '#666666',
primary: '#007AFF',
border: '#E5E5E5',
};
const darkColors = {
background: '#1A1A1A',
surface: '#2D2D2D',
text: '#FFFFFF',
textSecondary: '#A0A0A0',
primary: '#0A84FF',
border: '#3D3D3D',
};
const ThemeContext = createContext<ThemeContextValue | null>(null);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
// DevTools emulation triggers colorScheme changes via setEmulatedMedia
const systemColorScheme = useColorScheme();
const [theme, setTheme] = useState<Theme>(systemColorScheme ?? 'light');
useEffect(() => {
// Listen for DevTools theme emulation changes
const subscription = Appearance.addChangeListener(({ colorScheme }) => {
if (colorScheme) {
setTheme(colorScheme);
}
});
return () => subscription?.remove();
}, []);
const toggleTheme = () => setTheme(prev => (prev === 'light' ? 'dark' : 'light'));
const colors = theme === 'dark' ? darkColors : lightColors;
return (
<ThemeContext.Provider value={{ theme, toggleTheme, colors }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme(): ThemeContextValue {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
}O estado de emulação de mídia é reiniciado quando o DevTools se desconecta, garantindo que as builds de produção não sejam afetadas pelos testes de tema realizados durante o desenvolvimento.
Perguntas de Entrevista: React Native 0.86 e Edge-to-Edge
As entrevistas técnicas em 2026 estão cada vez mais focadas na compatibilidade com Android 15 e implementação edge-to-edge. Dominar esses conceitos demonstra compreensão das práticas modernas de desenvolvimento móvel. Para uma preparação completa de entrevistas, é possível explorar o módulo perguntas de entrevista sobre debugging em React Native.
O que é o modo edge-to-edge e por que o Android 15 o impõe?
O modo edge-to-edge estende o conteúdo do aplicativo sob os elementos de interface do sistema (barra de status, barra de navegação, indicadores de gestos). O Android 15 impõe esse comportamento por padrão para fornecer experiências imersivas e interface consistente em toda a plataforma. Os aplicativos devem lidar com os insets de área segura para evitar que o conteúdo seja ocultado pela interface do sistema.
Como o comportamento do measureInWindow muda com edge-to-edge habilitado?
Antes do React Native 0.86, measureInWindow retornava coordenadas relativas à janela visível, que excluía as áreas de interface do sistema. Com edge-to-edge, a janela se estende até as bordas da tela, mas as medições estavam incorretamente deslocadas. A versão 0.86 garante que as coordenadas sejam precisas independentemente do estado edge-to-edge.
Qual é o behavior do KeyboardAvoidingView recomendado no Android 15?
Recomenda-se usar behavior="padding" no Android 15 com edge-to-edge habilitado. O behavior height pode causar saltos de layout porque o cálculo da altura disponível muda quando o teclado aparece. O behavior padding fornece transições mais suaves e posicionamento mais previsível.
Como os insets de área segura diferem entre iOS e Android edge-to-edge?
No iOS, os insets de área segura existem desde o iPhone X para o notch e indicador de início. No Android edge-to-edge, os insets incluem a altura da barra de status, altura da barra de navegação e áreas de indicador de gestos. A biblioteca react-native-safe-area-context fornece valores de insets multiplataforma através de useSafeAreaInsets().
Pressable android_ripple com PlatformColor
O React Native 0.86 adiciona suporte de PlatformColor à prop android_ripple, permitindo cores de ripple dinâmicas que respeitam as configurações de tema do sistema.
import React from 'react';
import { Pressable, Text, PlatformColor, Platform, StyleSheet } from 'react-native';
interface ThemedButtonProps {
title: string;
onPress: () => void;
}
export function ThemedButton({ title, onPress }: ThemedButtonProps) {
return (
<Pressable
onPress={onPress}
style={({ pressed }) => [
styles.button,
pressed && styles.pressed,
]}
android_ripple={{
// PlatformColor adapts to system theme automatically
color: Platform.OS === 'android'
? PlatformColor('?attr/colorControlHighlight')
: undefined,
borderless: false,
foreground: true,
}}
>
<Text style={styles.text}>{title}</Text>
</Pressable>
);
}
const styles = StyleSheet.create({
button: {
padding: 16,
backgroundColor: Platform.select({
android: PlatformColor('?attr/colorPrimary'),
default: '#007AFF',
}),
borderRadius: 8,
alignItems: 'center',
},
pressed: { opacity: 0.8 },
text: { color: '#FFFFFF', fontWeight: '600', fontSize: 16 },
});Usar ?attr/colorControlHighlight garante que a cor do ripple corresponda às diretrizes do Material Design e se adapte aos temas claro/escuro configurados no nível do sistema.
Image.getSize Retorna Dimensões Precisas
Os métodos Image.getSize e Image.getSizeWithHeaders agora retornam as dimensões originais da imagem em vez de valores subamostrados. Essa correção é essencial para implementar cálculos corretos de proporção de aspecto e layouts de imagem responsivos.
import React, { useState, useEffect } from 'react';
import { Image, View, useWindowDimensions, StyleSheet } from 'react-native';
interface ResponsiveImageProps {
uri: string;
maxHeight?: number;
}
export function ResponsiveImage({ uri, maxHeight = 400 }: ResponsiveImageProps) {
const { width: screenWidth } = useWindowDimensions();
const [dimensions, setDimensions] = useState({ width: screenWidth, height: 200 });
useEffect(() => {
// getSize now returns true source dimensions, not downsampled values
Image.getSize(
uri,
(width, height) => {
const aspectRatio = width / height;
let calculatedHeight = screenWidth / aspectRatio;
// Constrain to maxHeight while maintaining aspect ratio
if (calculatedHeight > maxHeight) {
calculatedHeight = maxHeight;
}
setDimensions({
width: screenWidth,
height: calculatedHeight,
});
},
(error) => {
console.error('Failed to get image size:', error);
}
);
}, [uri, screenWidth, maxHeight]);
return (
<View style={styles.container}>
<Image
source={{ uri }}
style={{ width: dimensions.width, height: dimensions.height }}
resizeMode="cover"
/>
</View>
);
}
const styles = StyleSheet.create({
container: { width: '100%' },
});Essa correção elimina a necessidade de soluções alternativas que obtinham as dimensões da imagem através de módulos nativos ou processamento de imagens do lado do servidor.
Tratamento de Grandes Respostas HTTP Sem OutOfMemoryError
O NetworkingModule anteriormente lançava OutOfMemoryError ao tratar grandes respostas HTTP. A versão 0.86 implementa processamento em chunks para respostas que excedem os limites de memória.
import { useState, useCallback } from 'react';
interface DownloadProgress {
loaded: number;
total: number;
percentage: number;
}
export function useLargeFileDownload() {
const [progress, setProgress] = useState<DownloadProgress | null>(null);
const [error, setError] = useState<string | null>(null);
const downloadFile = useCallback(async (url: string): Promise<Blob | null> => {
try {
setError(null);
setProgress({ loaded: 0, total: 0, percentage: 0 });
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const contentLength = response.headers.get('Content-Length');
const total = contentLength ? parseInt(contentLength, 10) : 0;
// NetworkingModule now handles large responses without OutOfMemoryError
const reader = response.body?.getReader();
if (!reader) {
throw new Error('Response body is not readable');
}
const chunks: Uint8Array[] = [];
let loaded = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
loaded += value.length;
setProgress({
loaded,
total,
percentage: total > 0 ? Math.round((loaded / total) * 100) : 0,
});
}
const blob = new Blob(chunks);
setProgress({ loaded, total, percentage: 100 });
return blob;
} catch (err) {
const message = err instanceof Error ? err.message : 'Download failed';
setError(message);
return null;
}
}, []);
return { downloadFile, progress, error };
}Para downloads de arquivos que excedam 50MB, recomenda-se usar react-native-blob-util ou bibliotecas similares de manipulação de arquivos nativos para melhor gerenciamento de memória.
Correção do Header Cookie no WebSocket
O header Cookie passado através do construtor WebSocket estava sendo removido antes de chegar ao servidor. Isso impedia a autenticação baseada em sessões para conexões WebSocket.
type MessageHandler = (data: string) => void;
type ErrorHandler = (error: Event) => void;
interface WebSocketOptions {
url: string;
sessionCookie: string;
onMessage: MessageHandler;
onError?: ErrorHandler;
}
export function createAuthenticatedWebSocket({
url,
sessionCookie,
onMessage,
onError,
}: WebSocketOptions): WebSocket {
// Cookie header now reaches the server correctly in 0.86
const ws = new WebSocket(url, undefined, {
headers: {
Cookie: sessionCookie,
// Additional headers as needed
'X-Client-Version': '1.0.0',
},
});
ws.onopen = () => {
console.log('WebSocket connected with session cookie');
};
ws.onmessage = (event) => {
if (typeof event.data === 'string') {
onMessage(event.data);
}
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
onError?.(error);
};
ws.onclose = (event) => {
console.log(`WebSocket closed: ${event.code} ${event.reason}`);
};
return ws;
}Essa correção é crítica para aplicações que usam gerenciamento de sessões baseado em cookies junto com funcionalidades em tempo real. O módulo perguntas de entrevista sobre networking em React Native cobre em profundidade os padrões de implementação WebSocket.
Conclusão
- O React Native 0.86 entrega as correções edge-to-edge obrigatórias para Android 15 sem mudanças que quebram compatibilidade
measureInWindow,KeyboardAvoidingVieweDimensionsfuncionam corretamente com edge-to-edge habilitado- As atualizações da StatusBar agora se aplicam enquanto os componentes Modal estão visíveis
- A emulação de tema no DevTools acelera o desenvolvimento e testes do modo escuro
- O suporte de
PlatformColornoandroid_ripplepermite feedback tátil adaptado ao tema Image.getSizeretorna dimensões originais precisas para layouts responsivos- Grandes respostas HTTP não causam mais
OutOfMemoryError - Os headers Cookie do WebSocket chegam ao servidor como esperado
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Tags
Compartilhar
Artigos relacionados

React Native e TypeScript em 2026: Arquitetura Type-Safe e Perguntas de Entrevista
Construir aplicações React Native robustas com TypeScript, Codegen, TurboModules e a API Strict TypeScript. Arquitetura type-safe, navegação tipada e perguntas de entrevista técnica para 2026.

Expo Router no React Native: Guia Completo de Navegação Baseada em Arquivos
Guia completo do Expo Router para React Native com navegação baseada em arquivos, rotas dinâmicas, tabs, modais, rotas tipadas e proteção de rotas. Exemplos práticos com código.

Nova Arquitetura do React Native em 2026: Hermes V1, Modo Bridgeless e Perguntas de Entrevista
A Nova Arquitetura do React Native é agora o padrão em 2026 com Hermes V1, Modo Bridgeless, TurboModules e Fabric. Análise aprofundada dos ganhos de performance, padrões de migração e perguntas essenciais de entrevista.