十二月 21, 2025
49 分钟阅读

高级 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. 解释 useMemouseCallback。应该在何时使用它们?

答案: 这两个 Hook 都能通过记忆值/函数来优化性能。

  • useMemo: 记忆计算值(昂贵的计算)
  • useCallback: 记忆函数引用(防止重新创建)
  • 何时使用: 仅在遇到性能问题时使用。过早优化会使代码更难阅读。
import { useMemo, useCallback, useState } from 'react';

function ExpensiveComponent({ items, onItemClick }) {
  // useMemo - 记忆昂贵的计算
  const sortedItems = useMemo(() => {
    console.log('Sorting items...');
    return items.sort((a, b) => a.price - b.price);
  }, [items]); // 仅当 items 改变时才重新计算
  
  // useCallback - 记忆函数
  const handleClick = useCallback((id) => {
    console.log('Item clicked:', 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('Rendering item:', 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('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>
  );
}

// 定时器示例
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. 解释自定义 Hook,以及何时创建它们。

答案: 自定义 Hook 将可重用的有状态逻辑提取到单独的函数中。

  • 优点: 代码重用、关注点分离、更易于测试
  • 约定: 必须以 "use" 开头
// 用于 API 获取的自定义 Hook
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
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 提供了一种在组件树中传递数据的方式,而无需逐层传递 props。

  • 使用场景: 主题、身份验证、语言偏好
  • 注意: 如果使用不当,可能会导致不必要的重新渲染
import { createContext, useContext, useState } from 'react';

// 创建 context
const ThemeContext = createContext();
const AuthContext = createContext();

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

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

// 用于 context 的自定义 Hook
function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within 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. 解释 useEffectuseLayoutEffect 之间的区别。

答案: 两者都运行副作用,但在不同的时间:

  • 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('Component rendered');
  }, []);
  
  return (
    <View ref={elementRef}>
      <Text>Height: {height}</Text>
    </View>
  );
}

稀有度: 中等 难度: 困难


状态管理 (4 个问题)

6. 解释 Redux 及其核心原则。

答案: Redux 是 JavaScript 应用程序的可预测状态容器。

Loading diagram...
  • 核心原则:
    • 单一数据源(一个 store)
    • 状态是只读的(派发 action 来更改)
    • 使用纯函数进行更改(reducers)
// Action 类型
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';

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

// 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(组合 actions 和 reducer)
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;

// Store
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: 最小化,基于 Hook
  • 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 中处理副作用?

答案: 使用中间件进行异步操作:

  • Redux Thunk: 返回函数的函数
  • Redux Saga: 基于 Generator,更强大
  • 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('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}
    />
  );
}

稀有度: 非常常见 难度: 中等


11. 什么是 React Native bridge?它如何影响性能?

答案: Bridge 是 JavaScript 和原生代码之间的通信层。

  • 工作原理:
    • JavaScript 在单独的线程中运行
    • 原生模块在原生线程中运行
    • Bridge 在它们之间序列化数据(JSON)
  • 性能影响:
    • Bridge 通信是异步的
    • 序列化开销
    • 频繁通信可能成为瓶颈
  • 解决方案:
    • 最小化 bridge 跨越
    • 批量操作
    • 使用原生动画(绕过 bridge)
    • 新架构(JSI)移除 bridge
// 糟糕 - 频繁的 bridge 跨越
const BadAnimation = () => {
  const [position, setPosition] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setPosition(p => p + 1); // 每帧都跨越 bridge!
    }, 16);
    return () => clearInterval(interval);
  }, []);
  
  return <View style={{ transform: [{ translateX: position }] }} />;
};

// 良好 - 原生动画(无 bridge)
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. 适当的 key props: 帮助 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('Rendering 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 性能分析
// 在开发模式下启用性能监视器
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 接口)- 直接 C++ 通信
    • 无 bridge 序列化

优点:

  • 更快的启动
  • 更低的内存使用
  • 同步原生调用
  • 更好的类型安全

稀有度: 中等 难度: 困难


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('Opened with 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 Linking.openURL(url);
  }
};

稀有度: 常见 难度: 中等


测试 (3 个问题)

19. 如何测试 React Native 组件?

答案: 使用诸如 Jest 和 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: () => Promise.resolve({ name: 'John' }),
      })
    );
    global.fetch = mockFetch;
    
    const { getByText } = render(<UserProfile userId={1} />);
    
    await waitFor(() => {
      expect(getByText('John')).toBeTruthy();
    });
    
    expect(mockFetch).toHaveBeenCalledWith('https://api.example.com/users/1');
  });
});

// 具有 testID 的组件
function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <View>
      <Text>Count: {count}</Text>
      <Button
        testID="increment-button"
        title="Increment"
        onPress={() => setCount(c => c + 1)}
      />
    </View>
  );
}

稀有度: 常见 难度: 中等


20. 如何测试 Redux 逻辑?

答案: 分别测试 reducers、actions 和连接的组件。

import todos
Newsletter subscription

真正有效的每周职业建议

将最新见解直接发送到您的收件箱

Decorative doodle

创建一份让您被录用速度提高60%的简历

在几分钟内,创建一份量身定制的、ATS友好的简历,已证明可以获得6倍以上的面试机会。

创建更好的简历

分享这篇文章

让您的6秒钟发挥作用

招聘人员平均只花6到7秒扫描简历。我们经过验证的模板旨在立即吸引注意力并让他们继续阅读。