# 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. - Published: 2026-07-18 - Updated: 2026-07-18 - Author: SharpSkill - Tags: react-native, android, mobile-development, edge-to-edge, devtools - Reading time: 12 min --- 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. > **Zero Mudanças que Quebram Compatibilidade** > > 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. ```typescript // SafeAreaHandler.tsx 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(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 ( Show Tooltip ); } 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](https://reactnative.dev/docs/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. ```typescript // ChatInput.tsx 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 ( {/* Chat messages would render here */} ); } 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. ```typescript // ThemedModal.tsx 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 Content Close ); } 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. ## Emulação de Modo Claro e Escuro no DevTools O React Native DevTools introduz suporte para [Emulation.setEmulatedMedia](https://chromedevtools.github.io/devtools-protocol/tot/Emulation/#method-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). ```typescript // ThemeProvider.tsx 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(null); export function ThemeProvider({ children }: { children: React.ReactNode }) { // DevTools emulation triggers colorScheme changes via setEmulatedMedia const systemColorScheme = useColorScheme(); const [theme, setTheme] = useState(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 ( {children} ); } 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](/technologies/react-native/interview-questions/rn-debugging). ### 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](https://reactnative.dev/docs/platformcolor) à prop `android_ripple`, permitindo cores de ripple dinâmicas que respeitam as configurações de tema do sistema. ```typescript // ThemedButton.tsx 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 ( [ 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, }} > {title} ); } 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. ```typescript // ResponsiveImage.tsx 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 ( ); } 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. ```typescript // LargeFileDownload.tsx import { useState, useCallback } from 'react'; interface DownloadProgress { loaded: number; total: number; percentage: number; } export function useLargeFileDownload() { const [progress, setProgress] = useState(null); const [error, setError] = useState(null); const downloadFile = useCallback(async (url: string): Promise => { 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](https://github.com/RonRadtke/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. ```typescript // AuthenticatedWebSocket.ts 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](/technologies/react-native/interview-questions/rn-networking-api) 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`, `KeyboardAvoidingView` e `Dimensions` funcionam 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 `PlatformColor` no `android_ripple` permite feedback tátil adaptado ao tema - `Image.getSize` retorna 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 --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/react-native/react-native-086-edge-to-edge-android-devtools-interview-questions