dezembro 21, 2025
18 min de leitura

Perguntas para Entrevista de Desenvolvedor React Native Sênior: Guia Completo

interview
career-advice
job-search
Perguntas para Entrevista de Desenvolvedor React Native Sênior: Guia Completo
Milad Bonakdar

Milad Bonakdar

Autor

Domine o desenvolvimento React Native avançado com perguntas essenciais para entrevistas, abrangendo otimização de desempenho, módulos nativos, gerenciamento de estado, testes, padrões de arquitetura e melhores práticas multiplataforma para desenvolvedores seniores.


Introdução

Espera-se que desenvolvedores React Native sênior arquitetem aplicativos multiplataforma escaláveis, otimizem o desempenho, integrem módulos nativos e tomem decisões arquitetônicas informadas. Essa função exige profundo conhecimento em React Native, gerenciamento de estado, desenvolvimento nativo e a capacidade de resolver desafios complexos de desenvolvimento móvel.

Este guia abrangente cobre as principais perguntas de entrevistas para desenvolvedores React Native sênior, abrangendo conceitos avançados de React, otimização de desempenho, gerenciamento de estado, módulos nativos, testes e padrões arquitetônicos. Cada pergunta inclui respostas detalhadas, avaliação de raridade e classificações de dificuldade.


React e Hooks Avançados (5 Perguntas)

1. Explique useMemo e useCallback. Quando você deve usá-los?

Resposta: Ambos os hooks otimizam o desempenho memorizando valores/funções.

  • useMemo: Memoriza valores computados (cálculos caros)
  • useCallback: Memoriza referências de função (evita a recriação)
  • Quando usar: Apenas quando você tiver problemas de desempenho. A otimização prematura pode tornar o código mais difícil de ler.
import { useMemo, useCallback, useState } from 'react';

function ExpensiveComponent({ items, onItemClick }) {
  // useMemo - memoriza cálculo caro
  const sortedItems = useMemo(() => {
    console.log('Sorting items...');
    return items.sort((a, b) => a.price - b.price);
  }, [items]); // Recalcula apenas quando os itens mudam
  
  // useCallback - memoriza função
  const handleClick = useCallback((id) => {
    console.log('Item clicked:', id);
    onItemClick(id);
  }, [onItemClick]); // Recria apenas quando onItemClick muda
  
  return (
    <FlatList
      data={sortedItems}
      renderItem={({ item }) => (
        <ItemRow item={item} onClick={handleClick} />
      )}
    />
  );
}

// Componente filho com React.memo
const ItemRow = React.memo(({ item, onClick }) => {
  console.log('Rendering item:', item.id);
  return (
    <TouchableOpacity onPress={() => onClick(item.id)}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

Raridade: Muito Comum Dificuldade: Média


2. O que é useRef e quais são seus casos de uso?

Resposta: useRef cria uma referência mutável que persiste entre renderizações sem causar novas renderizações.

  • Casos de Uso:
    • Acessar elementos DOM/nativos
    • Armazenar valores mutáveis sem disparar nova renderização
    • Manter valores anteriores
    • Armazenar timers/intervalos
import { useRef, useEffect } from 'react';
import { TextInput, Animated } from 'react-native';

function FormComponent() {
  const inputRef = useRef(null);
  const previousValue = useRef('');
  const animatedValue = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    // Foca o input ao montar
    inputRef.current?.focus();
  }, []);
  
  const handleChange = (text) => {
    console.log('Previous:', previousValue.current);
    console.log('Current:', text);
    previousValue.current = text;
  };
  
  const startAnimation = () => {
    Animated.timing(animatedValue, {
      toValue: 1,
      duration: 300,
      useNativeDriver: true,
    }).start();
  };
  
  return (
    <View>
      <TextInput ref={inputRef} onChangeText={handleChange} />
      <Animated.View style={{ opacity: animatedValue }}>
        <Text>Animated Content</Text>
      </Animated.View>
    </View>
  );
}

// Exemplo de Timer
function Timer() {
  const intervalRef = useRef(null);
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setCount(c => c + 1);
    }, 1000);
    
    return () => clearInterval(intervalRef.current);
  }, []);
  
  return <Text>{count}</Text>;
}

Raridade: Comum Dificuldade: Média


3. Explique Hooks Personalizados e quando criá-los.

Resposta: Hooks personalizados extraem lógica stateful reutilizável em funções separadas.

  • Benefícios: Reutilização de código, separação de preocupações, teste mais fácil
  • Convenção: Deve começar com "use"
// Hook personalizado para buscar dados da API
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const json = await response.json();
        setData(json);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    fetchData();
  }, [url]);
  
  return { data, loading, error };
}

// Hook personalizado para manipulação de formulário
function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});
  
  const handleChange = (name, value) => {
    setValues(prev => ({ ...prev, [name]: value }));
  };
  
  const validate = (validationRules) => {
    const newErrors = {};
    Object.keys(validationRules).forEach(field => {
      const rule = validationRules[field];
      if (rule.required && !values[field]) {
        newErrors[field] = `${field} is required`;
      }
    });
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  return { values, errors, handleChange, validate };
}

// Uso
function UserProfile() {
  const { data, loading, error } = useFetch('https://api.example.com/user');
  const { values, errors, handleChange, validate } = useForm({
    name: '',
    email: '',
  });
  
  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Error: {error}</Text>;
  
  return <Text>{data.name}</Text>;
}

Raridade: Comum Dificuldade: Média


4. O que é React Context e quando você deve usá-lo?

Resposta: O Context fornece uma maneira de passar dados pela árvore de componentes sem prop drilling.

  • Casos de Uso: Tema, autenticação, preferências de idioma
  • Cuidado: Pode causar renderizações desnecessárias se não for usado com cuidado
import { createContext, useContext, useState } from 'react';

// Cria contexto
const ThemeContext = createContext();
const AuthContext = createContext();

// Provedor de Tema
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Provedor de Autenticação
function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  
  const login = async (credentials) => {
    const user = await loginAPI(credentials);
    setUser(user);
  };
  
  const logout = () => {
    setUser(null);
  };
  
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

// Hooks personalizados para contexto
function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider');
  }
  return context;
}

function useAuth() {
  return useContext(AuthContext);
}

// Uso
function App() {
  return (
    <ThemeProvider>
      <AuthProvider>
        <MainApp />
      </AuthProvider>
    </ThemeProvider>
  );
}

function ThemedButton() {
  const { theme, toggleTheme } = useTheme();
  const { user } = useAuth();
  
  return (
    <TouchableOpacity
      style={{ backgroundColor: theme === 'light' ? '#fff' : '#333' }}
      onPress={toggleTheme}
    >
      <Text>{user ? `Hello, ${user.name}` : 'Guest'}</Text>
    </TouchableOpacity>
  );
}

Raridade: Muito Comum Dificuldade: Média


5. Explique a diferença entre useEffect e useLayoutEffect.

Resposta: Ambos executam side effects, mas em momentos diferentes:

  • useEffect: Executa assincronamente após a renderização ser pintada na tela
  • useLayoutEffect: Executa sincronamente antes de pintar (bloqueia atualizações visuais)
  • Use useLayoutEffect quando: Você precisa medir o DOM ou evitar flicker visual
import { useEffect, useLayoutEffect, useRef, useState } from 'react';

function MeasureComponent() {
  const [height, setHeight] = useState(0);
  const elementRef = useRef(null);
  
  // useLayoutEffect - mede antes de pintar
  useLayoutEffect(() => {
    if (elementRef.current) {
      const { height } = elementRef.current.measure((x, y, width, height) => {
        setHeight(height);
      });
    }
  }, []);
  
  // useEffect - depois de pintar
  useEffect(() => {
    console.log('Component rendered');
  }, []);
  
  return (
    <View ref={elementRef}>
      <Text>Height: {height}</Text>
    </View>
  );
}

Raridade: Média Dificuldade: Difícil


Gerenciamento de Estado (4 Perguntas)

6. Explique Redux e seus princípios básicos.

Resposta: Redux é um contêiner de estado previsível para aplicativos JavaScript.

Loading diagram...
  • Princípios Básicos:
    • Única fonte de verdade (um store)
    • O estado é somente leitura (despache actions para alterar)
    • Alterações feitas com funções puras (reducers)
// Tipos de Action
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';

// Criadores de Action
const addTodo = (text) => ({
  type: ADD_TODO,
  payload: { id: Date.now(), text, completed: false },
});

const toggleTodo = (id) => ({
  type: TOGGLE_TODO,
  payload: id,
});

// Reducer
const todosReducer = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];
    case TOGGLE_TODO:
      return state.map(todo =>
        todo.id === action.payload
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
};

// Store
import { createStore } from 'redux';
const store = createStore(todosReducer);

// Componente React Native
import { useSelector, useDispatch } from 'react-redux';

function TodoList() {
  const todos = useSelector(state => state.todos);
  const dispatch = useDispatch();
  
  return (
    <View>
      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity onPress={() => dispatch(toggleTodo(item.id))}>
            <Text style={{ textDecorationLine: item.completed ? 'line-through' : 'none' }}>
              {item.text}
            </Text>
          </TouchableOpacity>
        )}
      />
      <Button title="Add" onPress={() => dispatch(addTodo('New Task'))} />
    </View>
  );
}

Raridade: Muito Comum Dificuldade: Difícil


7. O que é Redux Toolkit e como ele simplifica o Redux?

Resposta: Redux Toolkit é a maneira oficial recomendada de escrever lógica Redux.

  • Benefícios:
    • Menos boilerplate
    • Immer integrado para atualizações imutáveis
    • Inclui Redux Thunk
    • Melhor suporte para TypeScript
import { createSlice, configureStore } from '@reduxjs/toolkit';

// Slice (combina actions e reducer)
const todosSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      // Immer permite código "mutante"
      state.push({
        id: Date.now(),
        text: action.payload,
        completed: false,
      });
    },
    toggleTodo: (state, action) => {
      const todo = state.find(t => t.id === action.payload);
      if (todo) {
        todo.completed = !todo.completed;
      }
    },
  },
});

export const { addTodo, toggleTodo } = todosSlice.actions;

// Store
const store = configureStore({
  reducer: {
    todos: todosSlice.reducer,
  },
});

// Async thunk
import { createAsyncThunk } from '@reduxjs/toolkit';

export const fetchTodos = createAsyncThunk(
  'todos/fetchTodos',
  async () => {
    const response = await fetch('https://api.example.com/todos');
    return response.json();
  }
);

const todosSlice = createSlice({
  name: 'todos',
  initialState: { items: [], loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchTodos.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchTodos.fulfilled, (state, action) => {
        state.loading = false;
        state.items = action.payload;
      })
      .addCase(fetchTodos.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

Raridade: Comum Dificuldade: Média


8. Quais são as alternativas ao Redux para gerenciamento de estado?

Resposta: Existem várias soluções de gerenciamento de estado:

  • Context API + useReducer: Integrado, bom para aplicativos simples
  • MobX: Baseado em observable, menos boilerplate
  • Zustand: Mínimo, baseado em hooks
  • Recoil: Baseado em átomo, pelo Facebook
  • Jotai: Átomos primitivos
// Exemplo Zustand
import create from 'zustand';

const useStore = create((set) => ({
  todos: [],
  addTodo: (text) => set((state) => ({
    todos: [...state.todos, { id: Date.now(), text, completed: false }],
  })),
  toggleTodo: (id) => set((state) => ({
    todos: state.todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ),
  })),
}));

// Uso
function TodoList() {
  const { todos, addTodo, toggleTodo } = useStore();
  
  return (
    <View>
      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity onPress={() => toggleTodo(item.id)}>
            <Text>{item.text}</Text>
          </TouchableOpacity>
        )}
      />
    </View>
  );
}

Raridade: Comum Dificuldade: Média


9. Como você lida com side effects no Redux?

Resposta: Use middleware para operações assíncronas:

  • Redux Thunk: Funções que retornam funções
  • Redux Saga: Baseado em gerador, mais poderoso
  • Redux Observable: Baseado em RxJS
// Redux Thunk
const fetchUser = (userId) => async (dispatch) => {
  dispatch({ type: 'FETCH_USER_REQUEST' });
  
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const user = await response.json();
    dispatch({ type: 'FETCH_USER_SUCCESS', payload: user });
  } catch (error) {
    dispatch({ type: 'FETCH_USER_FAILURE', payload: error.message });
  }
};

// Uso
dispatch(fetchUser(123));

// Redux Saga
import { call, put, takeEvery } from 'redux-saga/effects';

function* fetchUserSaga(action) {
  try {
    const user = yield call(fetch, `https://api.example.com/users/${action.payload}`);
    const data = yield call([user, 'json']);
    yield put({ type: 'FETCH_USER_SUCCESS', payload: data });
  } catch (error) {
    yield put({ type: 'FETCH_USER_FAILURE', payload: error.message });
  }
}

function* watchFetchUser() {
  yield takeEvery('FETCH_USER_REQUEST', fetchUserSaga);
}

Raridade: Comum Dificuldade: Difícil


Otimização de Desempenho (5 Perguntas)

10. Como você otimiza o desempenho do FlatList?

Resposta: Várias estratégias melhoram a rolagem do FlatList:

  1. Use keyExtractor: Forneça chaves exclusivas
  2. getItemLayout: Ignore a medição para itens de altura fixa
  3. removeClippedSubviews: Desmonte as visualizações fora da tela (Android)
  4. maxToRenderPerBatch: Controle o tamanho do lote
  5. windowSize: Controle a janela renderizada
  6. initialNumToRender: Itens para renderizar inicialmente
  7. Memorize renderItem: Evite renderizações desnecessárias
import React, { memo, useCallback } from 'react';

const ITEM_HEIGHT = 80;

// Componente de item memorizado
const ListItem = memo(({ item, onPress }) => {
  return (
    <TouchableOpacity onPress={() => onPress(item.id)} style={{ height: ITEM_HEIGHT }}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

function OptimizedList({ data }) {
  const handlePress = useCallback((id) => {
    console.log('Pressed:', id);
  }, []);
  
  const renderItem = useCallback(({ item }) => (
    <ListItem item={item} onPress={handlePress} />
  ), [handlePress]);
  
  const keyExtractor = useCallback((item) => item.id.toString(), []);
  
  const getItemLayout = useCallback((data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  }), []);
  
  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={keyExtractor}
      getItemLayout={getItemLayout}
      removeClippedSubviews={true}
      maxToRenderPerBatch={10}
      updateCellsBatchingPeriod={50}
      initialNumToRender={10}
      windowSize={5}
    />
  );
}

Raridade: Muito Comum Dificuldade: Média


11. O que é a ponte React Native e como ela afeta o desempenho?

Resposta: A ponte é a camada de comunicação entre o JavaScript e o código nativo.

  • Como funciona:
    • JavaScript é executado em uma thread separada
    • Módulos nativos são executados em threads nativas
    • A ponte serializa dados entre eles (JSON)
  • Impacto no Desempenho:
    • A comunicação da ponte é assíncrona
    • Sobrecarga de serialização
    • Pode se tornar um gargalo com comunicação frequente
  • Soluções:
    • Minimize as travessias da ponte
    • Operações em lote
    • Use animações nativas (desvie da ponte)
    • Nova Arquitetura (JSI) remove a ponte
// Ruim - travessias frequentes da ponte
const BadAnimation = () => {
  const [position, setPosition] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setPosition(p => p + 1); // Travessia da ponte a cada frame!
    }, 16);
    return () => clearInterval(interval);
  }, []);
  
  return <View style={{ transform: [{ translateX: position }] }} />;
};

// Bom - animação nativa (sem ponte)
const GoodAnimation = () => {
  const translateX = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    Animated.timing(translateX, {
      toValue: 100,
      duration: 1000,
      useNativeDriver: true, // Executa na thread nativa!
    }).start();
  }, []);
  
  return <Animated.View style={{ transform: [{ translateX }] }} />;
};

Raridade: Comum Dificuldade: Difícil


12. Como você evita renderizações desnecessárias?

Resposta: Várias técnicas evitam renderizações desperdiçadas:

  1. React.memo: Memoriza componentes
  2. useMemo/useCallback: Memoriza valores/funções
  3. Props de chave adequadas: Ajuda o React a identificar alterações
  4. Evite objetos/arrays inline: Crie novas referências
  5. Divida os componentes: Componentes menores e focados
// Ruim - cria novo objeto a cada renderização
function BadComponent() {
  return <ChildComponent style={{ margin: 10 }} />; // Novo objeto!
}

// Bom - referência estável
const styles = StyleSheet.create({
  container: { margin: 10 },
});

function GoodComponent() {
  return <ChildComponent style={styles.container} />;
}

// React.memo com comparação personalizada
const ExpensiveComponent = React.memo(
  ({ data, onPress }) => {
    console.log('Rendering ExpensiveComponent');
    return (
      <View>
        <Text>{data.name}</Text>
        <Button onPress={onPress} />
      </View>
    );
  },
  (prevProps, nextProps) => {
    // Comparação personalizada - só renderiza novamente se data.id mudou
    return prevProps.data.id === nextProps.data.id;
  }
);

// Divida os componentes para isolar as renderizações
function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');
  
  return (
    <View>
      {/* Renderiza novamente apenas quando a contagem muda */}
      <CountDisplay count={count} />
      
      {/* Renderiza novamente apenas quando o texto muda */}
      <TextDisplay text={text} />
      
      <Button onPress={() => setCount(c => c + 1)} />
    </View>
  );
}

const CountDisplay = React.memo(({ count }) => <Text>{count}</Text>);
const TextDisplay = React.memo(({ text }) => <Text>{text}</Text>);

Raridade: Muito Comum Dificuldade: Média


13. Como você otimiza imagens no React Native?

Resposta: A otimização de imagem é crucial para o desempenho:

  1. Redimensione as imagens: Use dimensões apropriadas
  2. Armazene imagens em cache: Use bibliotecas como react-native-fast-image
  3. Carregamento lento: Carregue imagens sob demanda
  4. Carregamento progressivo: Mostre o espaço reservado primeiro
  5. Use o formato WebP: Melhor compressão
import FastImage from 'react-native-fast-image';

function OptimizedImage({ uri }) {
  return (
    <FastImage
      source={{
        uri,
        priority: FastImage.priority.normal,
        cache: FastImage.cacheControl.immutable,
      }}
      resizeMode={FastImage.resizeMode.cover}
      style={{ width: 200, height: 200 }}
    />
  );
}

// Carregamento progressivo de imagem
function ProgressiveImage({ thumbnailUri, fullUri }) {
  const [imageLoaded, setImageLoaded] = useState(false);
  
  return (
    <View>
      <Image
        source={{ uri: thumbnailUri }}
        style={styles.image}
        blurRadius={imageLoaded ? 0 : 5}
      />
      <Image
        source={{ uri: fullUri }}
        style={[styles.image, { opacity: imageLoaded ? 1 : 0 }]}
        onLoad={() => setImageLoaded(true)}
      />
    </View>
  );
}

// Pré-busca de imagem
import { Image } from 'react-native';

const prefetchImages = async (urls) => {
  const promises = urls.map(url => Image.prefetch(url));
  await Promise.all(promises);
};

Raridade: Comum Dificuldade: Média


14. Quais ferramentas você usa para profiling de desempenho?

Resposta: Várias ferramentas ajudam a identificar problemas de desempenho:

  • React DevTools Profiler: Tempos de renderização de componentes
  • Flipper: Ferramenta de depuração e profiling
  • Monitor de Desempenho: Monitor de FPS integrado
  • Systrace: Rastreamento de desempenho do Android
  • Instruments: Profiling de desempenho do iOS
// Ative o monitor de desempenho em desenvolvimento
import { LogBox } from 'react-native';

if (__DEV__) {
  // Mostra o monitor de desempenho
  require('react-native').unstable_enableLogBox();
}

// Meça o tempo de renderização do componente
import { Profiler } from 'react';

function onRenderCallback(
  id,
  phase,
  actualDuration,
  baseDuration,
  startTime,
  commitTime
) {
  console.log(`${id} (${phase}) took ${actualDuration}ms`);
}

function App() {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <MyComponent />
    </Profiler>
  );
}

// Rastreamento de desempenho personalizado
const measurePerformance = (name, fn) => {
  const start = performance.now();
  const result = fn();
  const end = performance.now();
  console.log(`${name} took ${end - start}ms`);
  return result;
};

Raridade: Comum Dificuldade: Média


Módulos Nativos e Específicos da Plataforma (4 Perguntas)

15. Como você cria um Módulo Nativo no React Native?

Resposta: Módulos nativos permitem que você use código específico da plataforma.

// iOS (Objective-C) - CalendarManager.m
#import "CalendarManager.h"
#import <React/RCTLog.h>

@implementation CalendarManager

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
  RCTLogInfo(@"Creating event %@ at %@", name, location);
}

@end

// Android (Java) - CalendarModule.java
package com.myapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class CalendarModule extends ReactContextBaseJavaModule {
  CalendarModule(ReactApplicationContext context) {
    super(context);
  }

  @Override
  public String getName() {
    return "CalendarManager";
  }

  @ReactMethod
  public void addEvent(String name, String location) {
    Log.d("CalendarModule", "Creating event " + name + " at " + location);
  }
}

// Uso em JavaScript
import { NativeModules } from 'react-native';

const { CalendarManager } = NativeModules;

function MyComponent() {
  const createEvent = () => {
    CalendarManager.addEvent('Meeting', 'Office');
  };
  
  return <Button title="Create Event" onPress={createEvent} />;
}

Raridade: Média Dificuldade: Difícil


16. Como você lida com código específico da plataforma?

Resposta: Várias abordagens para código específico da plataforma:

  1. Módulo de plataforma: Verifique a plataforma em tempo de execução
  2. Arquivos específicos da plataforma: .ios.js e .android.js
  3. Platform.select: Selecione valores com base na plataforma
import { Platform } from 'react-native';

// Módulo de plataforma
const styles = StyleSheet.create({
  container: {
    paddingTop: Platform.OS === 'ios' ? 20 : 0,
  },
});

// Platform.select
const styles = StyleSheet.create({
  container: {
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.3,
      },
      android: {
        elevation: 4,
      },
    }),
  },
});

// Arquivos específicos da plataforma
// Button.ios.js
export default function Button() {
  return <Text>iOS Button</Text>;
}

// Button.android.js
export default function Button() {
  return <Text>Android Button</Text>;
}

// Uso - seleciona automaticamente o arquivo correto
import Button from './Button';

// Verificação da versão da plataforma
if (Platform.Version >= 21) {
  // Android API 21+
}

Raridade: Muito Comum Dificuldade: Fácil


17. O que é a Nova Arquitetura (Fabric e TurboModules)?

Resposta: A Nova Arquitetura melhora o desempenho do React Native:

  • Fabric: Novo sistema de renderização
    • Layout síncrono
    • Melhor interoperação com visualizações nativas
    • Type safety
  • TurboModules: Novo sistema de módulo nativo
    • Carregamento lento
    • JSI (JavaScript Interface) - comunicação C++ direta
    • Sem serialização de ponte

Benefícios:

  • Inicialização mais rápida
  • Menor uso de memória
  • Chamadas nativas síncronas
  • Melhor type safety

Raridade: Média Dificuldade: Difícil


18. Como você lida com deep linking no React Native?

Resposta: Deep linking permite abrir telas específicas a partir de URLs.

import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';

// Configure deep linking
const linking = {
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: 'home',
      Profile: 'profile/:id',
      Settings: 'settings',
    },
  },
};

function App() {
  return (
    <NavigationContainer linking={linking}>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// Lida com links recebidos
useEffect(() => {
  const handleUrl = ({ url }) => {
    console.log('Opened with URL:', url);
    // myapp://profile/123
  };
  
  // Aplicativo aberto a partir do link
  Linking.getInitialURL().then(url => {
    if (url) handleUrl({ url });
  });
  
  // Aplicativo já aberto, novo link
  const subscription = Linking.addEventListener('url', handleUrl);
  
  return () => subscription.remove();
}, []);

// Abra a URL programaticamente
const openURL = async (url) => {
  const supported = await Linking.canOpenURL(url);
  if (supported) {
    await Linking.openURL(url);
  }
};

Raridade: Comum Dificuldade: Média


Testes (3 Perguntas)

19. Como você testa componentes React Native?

Resposta: Use bibliotecas de teste como Jest e React Native Testing Library.

import { render, fireEvent, waitFor } from '@testing-library/react-native';
import Counter from './Counter';

describe('Counter', () => {
  it('renders initial count', () => {
    const { getByText } = render(<Counter />);
    expect(getByText('Count: 0')).toBeTruthy();
  });
  
  it('increments count when button pressed', () => {
    const { getByText, getByTestId } = render(<Counter />);
    const button = getByTestId('increment-button');
    
    fireEvent.press(button);
    
    expect(getByText('Count: 1')).toBeTruthy();
  });
  
  it('fetches user data', async () => {
    const mockFetch = jest.fn(() =>
      Promise.resolve({
        json: ()
Newsletter subscription

Dicas de carreira semanais que realmente funcionam

Receba as últimas ideias diretamente na sua caixa de entrada

Crie um Currículo que Te Contrate 60% Mais Rápido

Em minutos, crie um currículo personalizado e compatível com ATS comprovado para conseguir 6 vezes mais entrevistas.

Crie um currículo melhor

Compartilhar esta publicação

Seja Contratado 50% Mais Rápido

Candidatos que usam currículos profissionais aprimorados por IA conseguem vagas em uma média de 5 semanas comparado às 10 padrão. Pare de esperar e comece a fazer entrevistas.