декабря 21, 2025
16 мин. чтения

Вопросы для собеседования на позицию старшего разработчика React Native: Полное руководство

interview
career-advice
job-search
Вопросы для собеседования на позицию старшего разработчика React Native: Полное руководство
MB

Milad Bonakdar

Автор

Освойте продвинутую разработку на React Native с помощью основных вопросов для собеседования, охватывающих оптимизацию производительности, собственные модули, управление состоянием, тестирование, шаблоны архитектуры и лучшие практики кроссплатформенной разработки для старших разработчиков.


Введение

От старших разработчиков React Native ожидается проектирование масштабируемых кроссплатформенных приложений, оптимизация производительности, интеграция нативных модулей и принятие обоснованных архитектурных решений. Эта роль требует глубоких знаний в React Native, управлении состоянием, нативной разработке и способности решать сложные задачи мобильной разработки.

Это всеобъемлющее руководство охватывает основные вопросы для собеседования старших разработчиков React Native, охватывающие продвинутые концепции React, оптимизацию производительности, управление состоянием, нативные модули, тестирование и архитектурные паттерны. Каждый вопрос включает подробные ответы, оценку редкости и уровни сложности.


Продвинутый React & Hooks (5 вопросов)

1. Объясните useMemo и useCallback. Когда их следует использовать?

Ответ: Оба хука оптимизируют производительность путем мемоизации значений/функций.

  • useMemo: Мемоизирует вычисляемые значения (дорогие вычисления)
  • useCallback: Мемоизирует ссылки на функции (предотвращает пересоздание)
  • Когда использовать: Только при наличии проблем с производительностью. Преждевременная оптимизация может затруднить чтение кода.
import { useMemo, useCallback, useState } from 'react';

function ExpensiveComponent({ items, onItemClick }) {
  // useMemo - мемоизация дорогостоящих вычислений
  const sortedItems = useMemo(() => {
    console.log('Сортировка элементов...');
    return items.sort((a, b) => a.price - b.price);
  }, [items]); // Пересчитывать только при изменении items
  
  // useCallback - мемоизация функции
  const handleClick = useCallback((id) => {
    console.log('Нажат элемент:', id);
    onItemClick(id);
  }, [onItemClick]); // Пересоздавать только при изменении onItemClick
  
  return (
    <FlatList
      data={sortedItems}
      renderItem={({ item }) => (
        <ItemRow item={item} onClick={handleClick} />
      )}
    />
  );
}

// Дочерний компонент с React.memo
const ItemRow = React.memo(({ item, onClick }) => {
  console.log('Отрисовка элемента:', item.id);
  return (
    <TouchableOpacity onPress={() => onClick(item.id)}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

Редкость: Очень часто Сложность: Средняя


2. Что такое useRef и каковы его варианты использования?

Ответ: useRef создает изменяемую ссылку, которая сохраняется между рендерами, не вызывая повторных рендеров.

  • Варианты использования:
    • Доступ к DOM/нативным элементам
    • Хранение изменяемых значений без вызова повторного рендера
    • Хранение предыдущих значений
    • Хранение таймеров/интервалов
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(() => {
    // Фокусировка на вводе при монтировании
    inputRef.current?.focus();
  }, []);
  
  const handleChange = (text) => {
    console.log('Предыдущее значение:', previousValue.current);
    console.log('Текущее значение:', 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>Анимированный контент</Text>
      </Animated.View>
    </View>
  );
}

// Пример с таймером
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>;
}

Редкость: Часто Сложность: Средняя


3. Объясните пользовательские хуки и когда их следует создавать.

Ответ: Пользовательские хуки извлекают повторно используемую логику с состоянием в отдельные функции.

  • Преимущества: Повторное использование кода, разделение ответственности, упрощение тестирования
  • Соглашение: Должно начинаться с "use"
// Пользовательский хук для получения данных 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 };
}

// Пользовательский хук для обработки форм
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 };
}

// Использование
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>;
}

Редкость: Часто Сложность: Средняя


4. Что такое React Context и когда его следует использовать?

Ответ: Context предоставляет способ передачи данных через дерево компонентов без проброса пропсов.

  • Варианты использования: Тема, аутентификация, языковые предпочтения
  • Предостережение: Может вызвать ненужные повторные рендеры, если использовать неосторожно
import { createContext, useContext, useState } from 'react';

// Создание контекста
const ThemeContext = createContext();
const AuthContext = createContext();

// Провайдер темы
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>
  );
}

// Провайдер аутентификации
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>
  );
}

// Пользовательские хуки для контекста
function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme должен использоваться внутри ThemeProvider');
  }
  return context;
}

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

// Использование
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>
  );
}

Редкость: Очень часто Сложность: Средняя


5. Объясните разницу между useEffect и useLayoutEffect.

Ответ: Оба запускают побочные эффекты, но в разное время:

  • useEffect: Запускается асинхронно после отрисовки на экране
  • useLayoutEffect: Запускается синхронно перед отрисовкой (блокирует визуальные обновления)
  • Используйте useLayoutEffect, когда: Вам нужно измерить DOM или предотвратить визуальное мерцание
import { useEffect, useLayoutEffect, useRef, useState } from 'react';

function MeasureComponent() {
  const [height, setHeight] = useState(0);
  const elementRef = useRef(null);
  
  // useLayoutEffect - измерение перед отрисовкой
  useLayoutEffect(() => {
    if (elementRef.current) {
      const { height } = elementRef.current.measure((x, y, width, height) => {
        setHeight(height);
      });
    }
  }, []);
  
  // useEffect - после отрисовки
  useEffect(() => {
    console.log('Компонент отрисован');
  }, []);
  
  return (
    <View ref={elementRef}>
      <Text>Высота: {height}</Text>
    </View>
  );
}

Редкость: Средняя Сложность: Высокая


Управление состоянием (4 вопроса)

6. Объясните Redux и его основные принципы.

Ответ: Redux - это предсказуемый контейнер состояния для JavaScript-приложений.

Loading diagram...
  • Основные принципы:
    • Единственный источник истины (одно хранилище)
    • Состояние доступно только для чтения (для изменения отправляйте действия)
    • Изменения вносятся с помощью чистых функций (редьюсеров)
// Типы действий
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';

// Создатели действий
const addTodo = (text) => ({
  type: ADD_TODO,
  payload: { id: Date.now(), text, completed: false },
});

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

// Редьюсер
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;
  }
};

// Хранилище
import { createStore } from 'redux';
const store = createStore(todosReducer);

// Компонент 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>
  );
}

Редкость: Очень часто Сложность: Высокая


7. Что такое Redux Toolkit и как он упрощает Redux?

Ответ: Redux Toolkit - это официально рекомендованный способ написания логики Redux.

  • Преимущества:
    • Меньше шаблонного кода
    • Встроенный Immer для неизменяемых обновлений
    • Включает Redux Thunk
    • Лучшая поддержка TypeScript
import { createSlice, configureStore } from '@reduxjs/toolkit';

// Slice (объединяет действия и редьюсер)
const todosSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      // Immer позволяет "изменять" код
      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;

// Хранилище
const store = configureStore({
  reducer: {
    todos: todosSlice.reducer,
  },
});

// Асинхронный 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;
      });
  },
});

Редкость: Часто Сложность: Средняя


8. Какие существуют альтернативы Redux для управления состоянием?

Ответ: Существует несколько решений для управления состоянием:

  • Context API + useReducer: Встроенный, хорошо подходит для простых приложений
  • MobX: На основе observable, меньше шаблонного кода
  • Zustand: Минимальный, на основе хуков
  • Recoil: На основе атомов, от Facebook
  • Jotai: Примитивные атомы
// Пример 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
    ),
  })),
}));

// Использование
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>
  );
}

Редкость: Часто Сложность: Средняя


9. Как вы обрабатываете побочные эффекты в Redux?

Ответ: Используйте middleware для асинхронных операций:

  • Redux Thunk: Функции, которые возвращают функции
  • Redux Saga: На основе генераторов, более мощный
  • Redux Observable: На основе 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 });
  }
};

// Использование
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);
}

Редкость: Часто Сложность: Высокая


Оптимизация производительности (5 вопросов)

10. Как оптимизировать производительность FlatList?

Ответ: Несколько стратегий улучшают прокрутку FlatList:

  1. Используйте keyExtractor: Предоставьте уникальные ключи
  2. getItemLayout: Пропустите измерение для элементов фиксированной высоты
  3. removeClippedSubviews: Размонтируйте представления за пределами экрана (Android)
  4. maxToRenderPerBatch: Управляйте размером пакета
  5. windowSize: Управляйте отображаемым окном
  6. initialNumToRender: Элементы для первоначальной отрисовки
  7. Мемоизируйте renderItem: Предотвратите ненужные повторные рендеры
import React, { memo, useCallback } from 'react';

const ITEM_HEIGHT = 80;

// Мемоизированный компонент элемента
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('Нажато:', 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}
    />
  );
}

Редкость: Очень часто Сложность: Средняя


11. Что такое мост React Native и как он влияет на производительность?

Ответ: Мост - это уровень связи между JavaScript и нативным кодом.

  • Как это работает:
    • JavaScript выполняется в отдельном потоке
    • Нативные модули выполняются в нативных потоках
    • Мост сериализует данные между ними (JSON)
  • Влияние на производительность:
    • Связь через мост является асинхронной
    • Накладные расходы на сериализацию
    • Может стать узким местом при частой связи
  • Решения:
    • Минимизируйте пересечения моста
    • Пакетные операции
    • Используйте нативные анимации (обходите мост)
    • Новая архитектура (JSI) удаляет мост
// Плохо - частые пересечения моста
const BadAnimation = () => {
  const [position, setPosition] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setPosition(p => p + 1); // Пересечение моста каждый кадр!
    }, 16);
    return () => clearInterval(interval);
  }, []);
  
  return <View style={{ transform: [{ translateX: position }] }} />;
};

// Хорошо - нативная анимация (без моста)
const GoodAnimation = () => {
  const translateX = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    Animated.timing(translateX, {
      toValue: 100,
      duration: 1000,
      useNativeDriver: true, // Выполняется в нативном потоке!
    }).start();
  }, []);
  
  return <Animated.View style={{ transform: [{ translateX }] }} />;
};

Редкость: Часто Сложность: Высокая


12. Как предотвратить ненужные повторные рендеры?

Ответ: Несколько методов предотвращают напрасные рендеры:

  1. React.memo: Мемоизируйте компоненты
  2. useMemo/useCallback: Мемоизируйте значения/функции
  3. Правильные props key: Помогают React идентифицировать изменения
  4. Избегайте встроенных объектов/массивов: Создавайте новые ссылки
  5. Разделите компоненты: Меньшие, сфокусированные компоненты
// Плохо - создает новый объект при каждом рендере
function BadComponent() {
  return <ChildComponent style={{ margin: 10 }} />; // Новый объект!
}

// Хорошо - стабильная ссылка
const styles = StyleSheet.create({
  container: { margin: 10 },
});

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

// React.memo с пользовательским сравнением
const ExpensiveComponent = React.memo(
  ({ data, onPress }) => {
    console.log('Отрисовка ExpensiveComponent');
    return (
      <View>
        <Text>{data.name}</Text>
        <Button onPress={onPress} />
      </View>
    );
  },
  (prevProps, nextProps) => {
    // Пользовательское сравнение - повторный рендер только при изменении data.id
    return prevProps.data.id === nextProps.data.id;
  }
);

// Разделите компоненты, чтобы изолировать повторные рендеры
function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');
  
  return (
    <View>
      {/* Повторный рендер только при изменении count */}
      <CountDisplay count={count} />
      
      {/* Повторный рендер только при изменении text */}
      <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>);

Редкость: Очень часто Сложность: Средняя


13. Как оптимизировать изображения в React Native?

Ответ: Оптимизация изображений имеет решающее значение для производительности:

  1. Измените размер изображений: Используйте соответствующие размеры
  2. Кэшируйте изображения: Используйте библиотеки, такие как react-native-fast-image
  3. Ленивая загрузка: Загружайте изображения по требованию
  4. Прогрессивная загрузка: Сначала покажите заполнитель
  5. Используйте формат WebP: Лучшее сжатие
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 }}
    />
  );
}

// Прогрессивная загрузка изображений
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>
  );
}

// Предварительная загрузка изображений
import { Image } from 'react-native';

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

Редкость: Часто Сложность: Средняя


14. Какие инструменты вы используете для профилирования производительности?

Ответ: Несколько инструментов помогают выявить проблемы с производительностью:

  • React DevTools Profiler: Время рендеринга компонентов
  • Flipper: Инструмент отладки и профилирования
  • Performance Monitor: Встроенный монитор FPS
  • Systrace: Трассировка производительности Android
  • Instruments: Профилирование производительности iOS
// Включите монитор производительности в dev
import { LogBox } from 'react-native';

if (__DEV__) {
  // Показывать монитор производительности
  require('react-native').unstable_enableLogBox();
}

// Измерение времени рендеринга компонента
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>
  );
}

// Пользовательское отслеживание производительности
const measurePerformance = (name, fn) => {
  const start = performance.now();
  const result = fn();
  const end = performance.now();
  console.log(`${name} took ${end - start}ms`);
  return result;
};

Редкость: Часто Сложность: Средняя


Нативные модули и специфичный для платформы код (4 вопроса)

15. Как создать нативный модуль в React Native?

Ответ: Нативные модули позволяют использовать специфичный для платформы код.

// 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);
  }
}

// Использование JavaScript
import { NativeModules } from 'react-native';

const { CalendarManager } = NativeModules;

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

Редкость: Средняя Сложность: Высокая


16. Как вы обрабатываете специфичный для платформы код?

Ответ: Несколько подходов для специфичного для платформы кода:

  1. Модуль Platform: Проверка платформы во время выполнения
  2. Файлы, специфичные для платформы: .ios.js и .android.js
  3. Platform.select: Выберите значения на основе платформы
import { Platform } from 'react-native';

// Модуль Platform
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,
      },
    }),
  },
});

// Файлы, специфичные для платформы
// Button.ios.js
export default function Button() {
  return <Text>iOS Button</Text>;
}

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

// Использование - автоматически выбирает правильный файл
import Button from './Button';

// Проверка версии платформы
if (Platform.Version >= 21) {
  // Android API 21+
}

Редкость: Очень часто Сложность: Легкая


17. Что такое новая архитектура (Fabric и TurboModules)?

Ответ: Новая архитектура улучшает производительность React Native:

  • Fabric: Новая система рендеринга
    • Синхронная разметка
    • Лучшая совместимость с нативными представлениями
    • Безопасность типов
  • TurboModules: Новая система нативных модулей
    • Ленивая загрузка
    • JSI (JavaScript Interface) - прямая связь C++
    • Нет сериализации моста

Преимущества:

  • Более быстрый запуск
  • Меньшее использование памяти
  • Синхронные нативные вызовы
  • Лучшая безопасность типов

Редкость: Средняя Сложность: Высокая


18. Как вы обрабатываете диплинки в React Native?

Ответ: Диплинки позволяют открывать определенные экраны из URL-адресов.

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

// Настройте диплинки
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>
  );
}

// Обработка входящих ссылок
useEffect(() => {
  const handleUrl = ({ url }) => {
    console.log('Открыто с URL:', url);
    // myapp://profile/123
  };
  
  // Приложение открыто по ссылке
  Linking.getInitialURL().then(url => {
    if (url) handleUrl({ url });
  });
  
  // Приложение уже открыто, новая ссылка
  const subscription = Linking.addEventListener('url', handleUrl);
  
  return () => subscription.remove();
}, []);

// Откройте URL программно
const openURL = async (url) => {
  const supported = await Linking.canOpenURL(url);
  if (supported) {
    await
Newsletter subscription

Еженедельные советы по карьере, которые действительно работают

Получайте последние идеи прямо на вашу почту

Похожие посты

Decorative doodle

Создайте резюме, которое поможет вам устроиться на 60% быстрее

За несколько минут создайте персонализированное резюме, совместимое с ATS, которое доказано увеличивает количество собеседований в 6 раз.

Создать лучшее резюме

Поделиться этим постом

Используйте Свои 6 Секунд По Максимуму

Рекрутеры просматривают резюме в среднем всего 6-7 секунд. Наши проверенные шаблоны разработаны так, чтобы мгновенно привлекать внимание и заставлять продолжать чтение.