React面试
时间: 2025-07-01 16:51:53 浏览: 15
### React 面试常见问题及解答
#### 1. 谈谈 React 中的受控组件和非受控组件的区别,并举例说明
在 React 中,**受控组件**是指其值由 React 组件的状态控制的表单元素。用户输入时,会触发事件处理函数来更新状态,进而通过状态更新重新渲染组件。例如:
```jsx
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
}
handleChange = (event) => {
this.setState({ value: event.target.value });
};
render() {
return (
<form>
<input type="text" value={this.state.value} onChange={this.handleChange} />
</form>
);
}
}
```
而**非受控组件**则使用 `ref` 来获取表单元素的值,而不是通过 React 的状态进行管理。例如:
```jsx
class NameForm extends React.Component {
inputRef = React.createRef();
handleSubmit = () => {
console.log(this.inputRef.current.value);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text" ref={this.inputRef} />
<button type="submit">Submit</button>
</form>
);
}
}
```
受控组件更符合 React 的设计理念,适合需要实时响应数据变化的场景;而非受控组件适用于简单快速获取表单值的情况[^1]。
---
#### 2. 解释 React 中的 Context API 以及它的优缺点
**Context API** 是 React 提供的一种机制,用于在组件树中传递数据,而无需手动将 props 逐层传递。它通过 `React.createContext()` 创建一个上下文对象,包含 `Provider` 和 `Consumer` 组件。例如:
```jsx
const ThemeContext = React.createContext('light');
// Provider 使用 value 属性提供值
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
// Consumer 在子组件中消费值
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
```
**优点**:
- 减少层级嵌套的 props 传递。
- 适用于全局共享的数据(如主题、语言等)。
**缺点**:
- 数据变化时,所有依赖该 context 的组件都会重新渲染。
- 可能导致性能问题,尤其是在大型应用中。
- 不易于调试,因为数据流不够直观[^1]。
---
#### 3. React 中如何实现代码分割(Code Splitting)
代码分割是优化加载性能的重要手段,React 支持以下几种方式实现:
- **动态导入(Dynamic Import)**:结合 `React.lazy` 和 `Suspense` 实现按需加载。
```jsx
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<React.Suspense fallback="Loading...">
<LazyComponent />
</React.Suspense>
);
}
```
- **路由级代码分割**:在 React Router 中按需加载不同页面组件。
```jsx
const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));
function App() {
return (
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}
```
- **Webpack 分块配置**:通过 Webpack 的 `SplitChunksPlugin` 对代码进行自动分块[^1]。
---
#### 4. 描述 React 中的错误边界(Error Boundaries)以及如何使用
**错误边界**是一种 React 组件,可以捕获并处理其子组件树中的 JavaScript 错误,防止整个应用崩溃。它通过定义 `static getDerivedStateFromError()` 或 `componentDidCatch()` 生命周期方法实现。
示例:
```jsx
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error('Caught an error:', error, info);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
```
使用时包裹可能出错的组件:
```jsx
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
```
需要注意的是,错误边界无法捕获异步错误或事件处理器中的错误[^1]。
---
#### 5. 解释 React 中的 Fiber 架构以及它解决了什么问题
**Fiber 架构**是 React 16 引入的核心重构之一,旨在提高渲染性能和用户体验。传统的 React 渲染过程是同步且不可中断的,可能导致主线程阻塞,影响交互体验。
Fiber 架构的主要特点包括:
- **可中断性**:允许 React 将渲染工作拆分为多个小任务,并在必要时暂停、恢复或优先处理更高优先级的任务。
- **增量渲染**:逐步渲染组件树,提升复杂应用的响应速度。
- **支持异步模式**:为未来的并发模式(Concurrent Mode)打下基础。
通过这些改进,React 可以更好地应对复杂的 UI 更新需求,避免页面卡顿[^1]。
---
#### 6. React 中如何处理事件
React 的事件系统是合成事件(SyntheticEvent),它对原生浏览器事件进行了封装,确保跨浏览器一致性。事件处理通常通过内联函数或类组件的方法绑定实现。
示例:
```jsx
class Button extends React.Component {
handleClick = () => {
console.log('Button clicked');
};
render() {
return <button onClick={this.handleClick}>Click me</button>;
}
}
```
对于函数组件,可以直接在 JSX 中使用箭头函数:
```jsx
function Button() {
const handleClick = () => {
console.log('Button clicked');
};
return <button onClick={handleClick}>Click me</button>;
}
```
React 的事件处理与原生事件的区别在于:
- 所有事件都绑定在根节点上(事件委托)。
- 合成事件对象会被池化,不能异步访问[^1]。
---
#### 7. 如何在 React 中进行性能优化
React 提供了多种性能优化手段:
- **使用 `React.memo`**:避免不必要的组件重新渲染,适用于纯组件。
```jsx
const MemoizedComponent = React.memo(MyComponent);
```
- **使用 `useCallback` 和 `useMemo`**:缓存回调函数和计算结果,减少重复创建。
```jsx
const memoizedCallback = useCallback(() => {
// do something
}, [deps]);
```
- **代码分割**:如前所述,使用 `React.lazy` 和 `Suspense` 按需加载组件。
- **避免不必要的状态更新**:使用不可变数据更新状态,避免直接修改 state。
- **使用 `shouldComponentUpdate`**:在类组件中自定义是否
阅读全文
相关推荐


















