十二月 21, 2025
35 分钟阅读

初级 React Native 开发者面试题与答案

interview
career-advice
job-search
entry-level
初级 React Native 开发者面试题与答案
Milad Bonakdar

Milad Bonakdar

作者

练习初级 React Native 面试题,覆盖组件、Hooks、导航、API 请求、列表、AsyncStorage 和移动开发基础。


介绍

初级 React Native 面试通常会考察你是否能用 React 构建简单的移动端页面,解释原生渲染,用 Hooks 管理状态,在页面之间导航,请求 API 数据,并保存非敏感的本地数据。好的回答应该很实用:你会用什么、什么时候不用、它在 iOS 和 Android 上带来什么取舍。

这份指南帮助你练习第一份 React Native 岗位中最可能出现的问题。与其死记库的细节,不如重点掌握 React 基础、核心组件、导航、表单、列表、API 请求、存储和移动端调试。


React 基础知识 (6 个问题)

1. 什么是 React Native?它与 React 有何不同?

答案:

  • React: 用于构建 Web 用户界面的 JavaScript 库
  • React Native: 使用 React 构建原生移动应用程序的框架
  • 主要区别:
    • React Native 渲染到原生组件(而不是 DOM)
    • 使用原生 API 而不是 Web API
    • 不同的样式方法(没有 CSS,使用 StyleSheet)
    • 针对 iOS 和 Android 的平台特定代码
// React (Web)
import React from 'react';

function App() {
  return <div className="container">Hello Web</div>;
}

// React Native (Mobile)
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

function App() {
  return (
    <View style={styles.container}>
      <Text>Hello Mobile</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

稀有度: 非常常见 难度: 简单


2. React Native 中的核心组件有哪些?

答案: React Native 提供了映射到原生 UI 元素的内置组件:

  • View: 容器组件(类似于 Web 中的 div
  • Text: 显示文本(所有文本都必须在 Text 组件中)
  • Image: 显示图像
  • ScrollView: 可滚动容器
  • TextInput: 文本输入字段
  • TouchableOpacity/Pressable: 可触摸元素
  • FlatList: 高效的列表渲染
  • Button: 基本按钮组件
import {
  View,
  Text,
  Image,
  TextInput,
  TouchableOpacity,
  StyleSheet,
} from 'react-native';

function MyComponent() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Welcome</Text>
      <Image source={{ uri: 'https://example.com/image.jpg' }} style={styles.image} />
      <TextInput placeholder="Enter name" style={styles.input} />
      <TouchableOpacity style={styles.button} onPress={() => console.log('Pressed')}>
        <Text style={styles.buttonText}>Click Me</Text>
      </TouchableOpacity>
    </View>
  );
}

稀有度: 非常常见 难度: 简单


3. 解释 ViewScrollView 之间的区别。

答案:

  • View: 静态容器。超出屏幕范围的内容不可滚动。
  • ScrollView: 可滚动容器。一次渲染所有子项(对于大型列表来说,可能会占用大量内存)。
  • 何时使用:
    • View: 用于适合屏幕的布局
    • ScrollView: 用于少量可滚动内容
    • FlatList: 用于大型列表(仅渲染可见项目)
// View - 不可滚动
<View style={{ height: 200 }}>
  <Text>Content 1</Text>
  <Text>Content 2</Text>
  {/* 如果内容超过 200px,则会被截断 */}
</View>

// ScrollView - 可滚动
<ScrollView style={{ height: 200 }}>
  <Text>Content 1</Text>
  <Text>Content 2</Text>
  <Text>Content 3</Text>
  {/* 可以滚动以查看所有内容 */}
</ScrollView>

// FlatList - 适用于大型列表
<FlatList
  data={items}
  renderItem={({ item }) => <Text>{item.name}</Text>}
  keyExtractor={item => item.id}
/>

稀有度: 非常常见 难度: 简单


4. 什么是 React Hooks?哪些是最常用的?

答案: Hooks 是允许您在函数组件中使用状态和生命周期特性的函数。

  • 常用 Hooks:
    • useState: 管理组件状态
    • useEffect: 处理副作用(数据获取、订阅)
    • useContext: 访问上下文值
    • useCallback: 记忆函数
    • useMemo: 记忆昂贵的计算
    • useRef: 引用 DOM 元素或持久化值
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';

function Counter() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    console.log(`Count changed to: ${count}`);
    
    // 清理函数
    return () => {
      console.log('Cleanup');
    };
  }, [count]); // 当 count 更改时运行
  
  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={() => setCount(count + 1)} />
    </View>
  );
}

稀有度: 非常常见 难度: 简单


5. 解释 useEffect 钩子及其依赖项数组。

答案: useEffect 在渲染后运行副作用。依赖项数组控制其运行时间:

  • 没有数组: 每次渲染后运行
  • 空数组 [] 在初始渲染后运行一次
  • 带有依赖项 [dep1, dep2] 当依赖项更改时运行
import { useEffect, useState } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  
  // 在挂载时运行一次
  useEffect(() => {
    console.log('Component mounted');
  }, []);
  
  // 当 userId 更改时运行
  useEffect(() => {
    fetchUser(userId).then(data => setUser(data));
  }, [userId]);
  
  // 每次渲染后运行(避免这样做)
  useEffect(() => {
    console.log('Rendered');
  });
  
  // 清理函数
  useEffect(() => {
    const subscription = subscribeToUpdates();
    
    return () => {
      subscription.unsubscribe(); // 在卸载时清理
    };
  }, []);
  
  return <Text>{user?.name}</Text>;
}

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


6. 什么是虚拟 DOM?React 如何使用它?

答案: Virtual DOM 是 React Web 开发中的概念:React 维护一个轻量级 UI 树,在状态变化后进行比较,并只更新发生变化的部分。在 React Native 中,同样的 reconciliation 思路仍然适用,但最终输出的是原生视图,而不是浏览器 DOM 节点。

  • 面试中可以这样说:
    1. 状态变化会触发受影响组件重新渲染
    2. React 会把新的组件树和之前的组件树进行比较
    3. React Native 会把必要更新应用到原生 UI 组件
    4. 仍然要通过稳定的 key、合理放置 state,以及只在真正解决重渲染问题时使用 memoization 来优化
  • 重要纠正: React Native 不会更新 HTML 或浏览器 DOM。

稀有度: 常见 难度: 简单


组件和 Props (4 个问题)

7. Props 和 State 之间有什么区别?

答案:

  • Props:
    • 从父组件传递到子组件
    • 只读(不可变)
    • 用于组件配置
  • State:
    • 在组件内管理
    • 可变(可以更改)
    • 用于动态数据
// 父组件
function ParentComponent() {
  const [count, setCount] = useState(0);
  
  return (
    <ChildComponent 
      title="Counter"  // Props
      count={count}    // Props
      onIncrement={() => setCount(count + 1)}  // Props
    />
  );
}

// 子组件
function ChildComponent({ title, count, onIncrement }) {
  // 无法修改 props
  // title = "New Title"; // 错误!
  
  return (
    <View>
      <Text>{title}</Text>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={onIncrement} />
    </View>
  );
}

稀有度: 非常常见 难度: 简单


8. 什么是函数组件与类组件?

答案:

  • 函数组件:
    • 语法更简单
    • 使用 hooks 进行状态和生命周期管理
    • 在现代 React 中首选
  • 类组件:
    • 较旧的方法
    • 使用 this.state 和生命周期方法
    • 仍然支持,但不太常见
// 函数组件(现代)
function Welcome({ name }) {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    console.log('Mounted');
  }, []);
  
  return <Text>Hello, {name}</Text>;
}

// 类组件(旧版)
class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  
  componentDidMount() {
    console.log('Mounted');
  }
  
  render() {
    return <Text>Hello, {this.props.name}</Text>;
  }
}

稀有度: 常见 难度: 简单


9. 如何将数据从子组件传递到父组件?

答案: 使用作为 props 传递的回调函数。

// 父组件
function ParentComponent() {
  const [message, setMessage] = useState('');
  
  const handleMessageFromChild = (msg) => {
    setMessage(msg);
  };
  
  return (
    <View>
      <Text>Message from child: {message}</Text>
      <ChildComponent onSendMessage={handleMessageFromChild} />
    </View>
  );
}

// 子组件
function ChildComponent({ onSendMessage }) {
  const [input, setInput] = useState('');
  
  const sendMessage = () => {
    onSendMessage(input); // 调用父组件的函数
  };
  
  return (
    <View>
      <TextInput value={input} onChangeText={setInput} />
      <Button title="Send to Parent" onPress={sendMessage} />
    </View>
  );
}

稀有度: 非常常见 难度: 简单


10. 什么是 key prop?为什么它很重要?

答案: key prop 帮助 React 识别列表中哪些项目已更改、添加或删除。

  • 目的: 优化渲染性能
  • 要求: 在同级元素中必须是唯一的,稳定的(如果列表可以更改,请不要使用索引)
// 好的 - 使用唯一 ID
function UserList({ users }) {
  return (
    <FlatList
      data={users}
      keyExtractor={item => item.id} // 唯一的 key
      renderItem={({ item }) => <Text>{item.name}</Text>}
    />
  );
}

// 不好 - 使用索引(如果列表可以更改,请避免使用)
function BadList({ items }) {
  return (
    <View>
      {items.map((item, index) => (
        <Text key={index}>{item}</Text> // 不要使用索引
      ))}
    </View>
  );
}

// 好的 - 使用唯一属性
function GoodList({ items }) {
  return (
    <View>
      {items.map(item => (
        <Text key={item.id}>{item.name}</Text>
      ))}
    </View>
  );
}

稀有度: 非常常见 难度: 简单


样式和布局 (3 个问题)

11. 如何在 React Native 中设置组件样式?

答案: React Native 使用 JavaScript 对象进行样式设置,而不是 CSS。

  • StyleSheet API: 创建优化的样式
  • 内联样式: 直接样式对象(性能较低)
  • Flexbox: 默认布局系统
import { View, Text, StyleSheet } from 'react-native';

function StyledComponent() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Title</Text>
      <Text style={[styles.text, styles.bold]}>Multiple styles</Text>
      <Text style={{ color: 'red' }}>Inline style</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
  },
  text: {
    fontSize: 16,
    color: '#666',
  },
  bold: {
    fontWeight: 'bold',
  },
});

稀有度: 非常常见 难度: 简单


12. 解释 React Native 中的 Flexbox。

答案: Flexbox 是 React Native 中的主要布局系统。

  • 主要属性:
    • flexDirection: rowcolumn(默认:column
    • justifyContent: 沿主轴对齐
    • alignItems: 沿交叉轴对齐
    • flex: 比例大小
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row', // 水平布局
    justifyContent: 'space-between', // 均匀分布项目
    alignItems: 'center', // 垂直居中
  },
  box1: {
    flex: 1, // 占用 1/3 的空间
    backgroundColor: 'red',
  },
  box2: {
    flex: 2, // 占用 2/3 的空间
    backgroundColor: 'blue',
  },
});

function FlexExample() {
  return (
    <View style={styles.container}>
      <View style={styles.box1} />
      <View style={styles.box2} />
    </View>
  );
}

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


13. marginpadding 之间有什么区别?

答案:

  • Padding: 组件内部的空间(内容和边框之间)
  • Margin: 组件外部的空间(组件和相邻组件之间)
const styles = StyleSheet.create({
  box: {
    margin: 20,        // 外部空间
    padding: 10,       // 内部空间
    backgroundColor: 'lightblue',
  },
  // 特定边
  specificBox: {
    marginTop: 10,
    marginBottom: 20,
    paddingLeft: 15,
    paddingRight: 15,
  },
  // 水平和垂直
  shorthand: {
    marginHorizontal: 20,  // 左右
    marginVertical: 10,    // 上下
    paddingHorizontal: 15,
    paddingVertical: 5,
  },
});

稀有度: 常见 难度: 简单


导航 (3 个问题)

14. 什么是 React Navigation?如何使用它?

答案: React Navigation 是 React Native 最流行的导航库。

  • 类型:
    • Stack Navigator: 屏幕堆栈(push/pop)
    • Tab Navigator: 底部标签栏
    • Drawer Navigator: 侧边抽屉菜单
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

function HomeScreen({ navigation }) {
  return (
    <View>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details', { itemId: 42 })}
      />
    </View>
  );
}

function DetailsScreen({ route, navigation }) {
  const { itemId } = route.params;
  
  return (
    <View>
      <Text>Details Screen</Text>
      <Text>Item ID: {itemId}</Text>
      <Button title="Go Back" onPress={() => navigation.goBack()} />
    </View>
  );
}

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


15. 如何在屏幕之间传递参数?

答案: 使用带有第二个参数的 navigate 函数来传递数据。

// 使用参数导航
function HomeScreen({ navigation }) {
  const user = { id: 1, name: 'John', email: '[email protected]' };
  
  return (
    <Button
      title="View Profile"
      onPress={() => navigation.navigate('Profile', { user })}
    />
  );
}

// 接收参数
function ProfileScreen({ route }) {
  const { user } = route.params;
  
  return (
    <View>
      <Text>Name: {user.name}</Text>
      <Text>Email: {user.email}</Text>
    </View>
  );
}

// 更新参数
function EditScreen({ navigation }) {
  const updateUser = () => {
    navigation.setParams({ user: updatedUser });
  };
  
  return <Button title="Update" onPress={updateUser} />;
}

稀有度: 非常常见 难度: 简单


16. 什么是导航选项?如何自定义标题栏?

答案: 导航选项控制屏幕外观和行为。

function HomeScreen({ navigation }) {
  useEffect(() => {
    navigation.setOptions({
      title: 'My Home',
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
      headerRight: () => (
        <Button title="Info" onPress={() => alert('Info')} />
      ),
    });
  }, [navigation]);
  
  return <View><Text>Home</Text></View>;
}

// 或者在导航器中设置
<Stack.Screen
  name="Home"
  component={HomeScreen}
  options={{
    title: 'My Home',
    headerStyle: { backgroundColor: '#f4511e' },
    headerTintColor: '#fff',
  }}
/>

稀有度: 常见 难度: 简单


数据和存储 (4 个问题)

17. 如何在 React Native 中从 API 获取数据?

答案: 使用 fetch API 或像 Axios 这样的库。

import { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    fetchUsers();
  }, []);
  
  const fetchUsers = async () => {
    try {
      const response = await fetch('https://api.example.com/users');
      
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      
      const data = await response.json();
      setUsers(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };
  
  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Error: {error}</Text>;
  
  return (
    <FlatList
      data={users}
      renderItem={({ item }) => <Text>{item.name}</Text>}
      keyExtractor={item => item.id.toString()}
    />
  );
}

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


18. 什么是 AsyncStorage?如何使用它?

答案: AsyncStorage 是一个异步 key-value 存储,适合保存少量、非敏感数据。

  • 适合场景: 主题选择、引导流程标记、缓存 JSON、简单偏好设置
  • 避免用于: 认证 token、API key、密码、大型数据集,以及需要复杂查询的数据
  • 敏感数据: 使用平台支持的安全存储,例如通过维护良好的库接入 iOS Keychain 或 Android 加密存储
import AsyncStorage from '@react-native-async-storage/async-storage';

const savePreference = async (theme) => {
  await AsyncStorage.setItem('theme', theme);
};

const loadPreference = async () => {
  return await AsyncStorage.getItem('theme');
};

稀有度: 非常常见 难度: 简单


19. FlatListScrollView 之间有什么区别?

答案:

  • ScrollView:
    • 一次渲染所有子项
    • 适用于小型列表
    • 对于大型列表来说,占用大量内存
  • FlatList:
    • 仅渲染可见项目(懒加载)
    • 适用于大型列表
    • 内置优化
// ScrollView - 渲染所有内容
<ScrollView>
  {items.map(item => (
    <View key={item.id}>
      <Text>{item.name}</Text>
    </View>
  ))}
</ScrollView>

// FlatList - 仅渲染可见项目
<FlatList
  data={items}
  renderItem={({ item }) => (
    <View>
      <Text>{item.name}</Text>
    </View>
  )}
  keyExtractor={item => item.id}
  // 性能优化
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
/>

稀有度: 非常常见 难度: 简单


20. 如何处理表单和用户输入?

答案: 使用带有状态的受控组件。

import { useState } from 'react';
import { View, TextInput, Button, Text } from 'react-native';

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [errors, setErrors] = useState({});
  
  const validate = () => {
    const newErrors = {};
    
    if (!email) {
      newErrors.email = 'Email is required';
    } else if (!/\S+@\S+\.\S+/.test(email)) {
      newErrors.email = 'Email is invalid';
    }
    
    if (!password) {
      newErrors.password = 'Password is required';
    } else if (password.length < 6) {
      newErrors.password = 'Password must be at least 6 characters';
    }
    
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  const handleSubmit = () => {
    if (validate()) {
      console.log('Form submitted:', { email, password });
      // 提交到 API
    }
  };
  
  return (
    <View>
      <TextInput
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
        autoCapitalize="none"
      />
      {errors.email && <Text style={{ color: 'red' }}>{errors.email}</Text>}
      
      <TextInput
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />
      {errors.password && <Text style={{ color: 'red' }}>{errors.password}</Text>}
      
      <Button title="Login" onPress={handleSubmit} />
    </View>
  );
}

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


Newsletter subscription

真正有效的每周职业建议

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

您的下一次面试只差一份简历

在几分钟内创建一份专业、优化的简历。无需设计技能——只有经过验证的结果。

创建我的简历

分享这篇文章

让面试回访翻倍

根据职位描述定制简历的候选人获得的面试机会是其他人的2.5倍。使用我们的AI为每一份申请即时自动定制您的简历。