以下是整理的 20 道 React 面試題,涵蓋基礎、進階和實戰應用,適用于社招或內推準備:
一、React 基礎(適合初中級)
-
React 中的組件有哪幾種?它們有什么區別?
-
什么是 JSX?它與 HTML 有什么不同?
-
React 是如何實現虛擬 DOM 的?它的優勢是什么?
-
組件的生命周期函數有哪些?React 18 中的變化是?
-
React 中 key 的作用是什么?為什么不能用 index 作為 key?
-
如何在函數組件中模擬 componentDidMount?
-
受控組件和非受控組件的區別?分別適用于什么場景?
-
React 中事件綁定有哪些方式?有什么坑需要注意?
-
如何實現組件之間的通信?
-
React 如何實現條件渲染和列表渲染?
二、Hooks 專題(React 16.8+)
-
useEffect 有哪些使用場景?依賴數組寫錯會帶來什么問題?
-
useRef 和 useState 的區別?分別適用于哪些場景?
-
React 中如何避免 useEffect 死循環?
-
如何實現一個自定義 Hook?能舉個例子嗎?
-
為什么不能在循環、條件或嵌套函數中調用 Hook?
三、性能優化與實戰技巧
-
React 中如何避免不必要的重新渲染?有哪些優化手段?
-
React.memo、useMemo 和 useCallback 的作用與區別?
-
React 中如何實現懶加載?如何配合 Suspense 使用?
-
如何在 React 中做錯誤邊界處理?為什么函數組件不能做?
-
React18 中 Concurrent Mode 是什么?對開發者有什么影響?
好的,下面是前 5 道 React 面試題,以八股文風格整理,方便記憶和背誦:
- React 中的組件有哪幾種?它們有什么區別?
答:
React 組件主要分為兩類:類組件(Class Component)與函數組件(Function Component)。
類組件通過 class 關鍵字定義,需繼承 React.Component,具備生命周期函數、this.state 和 this.setState 等特性;
函數組件最初為純展示組件,自 React 16.8 引入 Hook 后也能擁有狀態與副作用邏輯,寫法更簡潔。
當前推薦使用函數組件,因其更易組合復用,性能優化更簡單,官方也逐步棄用類組件。
- 什么是 JSX?它與 HTML 有什么不同?
答:
JSX 是 JavaScript 的語法擴展,允許在 JavaScript 中書寫類似 HTML 的代碼,用于描述 UI 結構。
JSX 本質是 React.createElement 的語法糖,最終會被編譯為 JavaScript 對象。
與 HTML 的不同點包括:
所有標簽必須閉合;
屬性使用駝峰命名,如 className、onClick;
表達式需用 {} 包裹;
可以嵌套任意 JS 表達式。
- React 是如何實現虛擬 DOM 的?它的優勢是什么?
答:
React 中的虛擬 DOM 是用 JavaScript 對象描述真實 DOM 結構的中間表示。每次狀態變化后,會生成新的虛擬 DOM 樹,并與舊的樹進行 Diff 運算,找出差異部分,再最小化更新真實 DOM。
其優勢包括:
避免直接操作真實 DOM,提高性能;
更好的跨平臺能力;
有利于實現時間切片、異步渲染等高級特性。
- 組件的生命周期函數有哪些?React 18 中的變化是?
答:
類組件的生命周期分為三個階段:
掛載階段:constructor → render → componentDidMount;
更新階段:shouldComponentUpdate → render → componentDidUpdate;
卸載階段:componentWillUnmount。
React 16 后廢棄部分不安全生命周期,如 componentWillMount,推薦使用 getDerivedStateFromProps 和 getSnapshotBeforeUpdate 替代。
React 18 推出了自動批處理與并發特性,對生命周期感知更強,建議使用函數組件 + Hook 替代類組件管理生命周期。
- React 中 key 的作用是什么?為什么不能用 index?
答:
key 是 React 用于識別列表中元素的唯一標識,在執行 Diff 算法時能更高效定位變動元素。
若使用 index,當列表順序改變時可能導致組件錯誤復用、狀態錯亂、動畫異常等問題。
應優先使用唯一且穩定的業務 id 作為 key,只有在列表靜態、不會增刪改時才可使用 index。
好的,繼續為你整理 第 6~10 題 的 React 八股文風格問答:
- 如何在函數組件中模擬 componentDidMount?
答:
函數組件中可使用 useEffect 模擬類組件的 componentDidMount。
寫法如下:
useEffect(() => {
// 初始化邏輯
}, []);
當 useEffect 的依賴數組傳入空數組 [] 時,表示該副作用函數僅在組件首次渲染時執行一次,行為等價于類組件中的 componentDidMount。
該模式常用于請求初始化數據、設置事件監聽、初始化定時器等場景。
- 受控組件和非受控組件的區別?分別適用于什么場景?
答:
React 中,表單組件可分為受控組件和非受控組件。
受控組件:其值受 React state 控制,通過 value 和 onChange 實現雙向綁定。
優點是數據可控,易于校驗和聯動;
非受控組件:直接操作 DOM 讀取表單值,通常配合 ref 使用。
適用場景:
受控組件適用于復雜交互和受狀態驅動的場景;
非受控組件適用于性能敏感或簡單場景,如登錄表單、文件上傳等。
- React 中事件綁定有哪些方式?有什么坑需要注意?
答:
React 中常見的事件綁定方式包括:
在 JSX 中綁定箭頭函數(推薦):
onClick={() => handleClick(id)}
在組件外定義綁定函數:
onClick={handleClick},注意需在 constructor 中 bind:
this.handleClick = this.handleClick.bind(this);
使用 class fields 語法(推薦):
handleClick = () => { … }
注意事項:
每次 render 重新創建箭頭函數會影響性能;
函數組件中事件默認具有自動綁定能力,不用顯式 bind;
React 事件是合成事件,非原生事件,具備跨瀏覽器兼容性,支持事件池優化(v17 之后逐步廢棄事件池機制)。
好的,以下是 第 11~15 題(Hooks 專題) 的八股文風格標準問答:
- useEffect 有哪些使用場景?依賴數組寫錯會帶來什么問題?
答:
useEffect 是 React 中用于處理副作用的 Hook,常見使用場景包括:
組件掛載時請求數據;
監聽事件或訂閱操作;
依賴變化時執行操作;
清理副作用(如定時器、訂閱)。
其語法如下:
useEffect(() => {
// 副作用邏輯
return () => {
// 清理邏輯
};
}, [dependencies]);
若依賴數組寫錯(漏依賴、寫錯變量等),可能導致:
副作用函數未正確觸發或頻繁執行;
狀態不一致、數據不同步;
引發死循環或內存泄漏。
應借助 ESLint 插件(如 eslint-plugin-react-hooks)自動校驗依賴項完整性。
- useRef 和 useState 的區別?分別適用于哪些場景?
答:
useRef 和 useState 都可用于在函數組件中存儲數據,但用途與行為不同:
useState:用于聲明響應式狀態,狀態變更會觸發組件重新渲染;
useRef:用于存儲可變值,變更不會觸發組件重新渲染,常用于保存 DOM 引用或跨渲染周期保存變量。
適用場景對比如下:
表單輸入值:useState;
DOM 節點操作:useRef;
記錄上一次狀態值或定時器 ID:useRef;
控制重新渲染邏輯:useRef 可避免因頻繁更新而導致的性能浪費。
- React 中如何避免 useEffect 死循環?
答:
useEffect 死循環通常由以下原因導致:
依賴數組中包含每次 render 都變化的值(如函數、對象、數組);
副作用函數中更新了依賴項所關聯的狀態。
解決方式包括:
使用 useCallback 或 useMemo 對函數和對象進行穩定處理;
合理拆分多個 useEffect,細化每個副作用的關注點;
使用空依賴數組 [] 表示只執行一次(等價于 componentDidMount);
嚴格遵循 ESLint 對依賴項的提示,必要時用注釋忽略。
- 如何實現一個自定義 Hook?能舉個例子嗎?
答:
自定義 Hook 是以 use 開頭的函數,用于復用邏輯片段,讓組件更簡潔、更易維護。
示例:封裝一個監聽窗口大小的 Hook
import { useState, useEffect } from ‘react’;
function useWindowSize() {
const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });
useEffect(() => {
const handleResize = () => {
setSize({ width: window.innerWidth, height: window.innerHeight });
};
window.addEventListener(‘resize’, handleResize);
return () => window.removeEventListener(‘resize’, handleResize);
}, []);
return size;
}
使用方式:
const { width, height } = useWindowSize();
該 Hook 封裝了監聽邏輯,提升代碼復用性和可讀性。
- 為什么不能在循環、條件或嵌套函數中調用 Hook?
答:
React 的 Hook 調用必須遵循 “Hook 規則”,即:
只能在函數組件或自定義 Hook 的頂層調用 Hook;
不能在循環、條件、嵌套函數中調用 Hook。
原因是 React 依賴調用順序識別每個 Hook 的位置。
若在條件或循環中調用 Hook,會導致調用順序不一致,破壞內部 Hook 棧,從而引發運行時錯誤或邏輯異常。
官方提供 ESLint 插件 eslint-plugin-react-hooks,可幫助開發者自動檢測 Hook 使用規范。
好的,下面是 第 16~20 題(性能優化與實戰技巧) 的 React 八股文風格標準問答:
- React 如何優化組件性能?有哪些常見手段?
答:
React 性能優化的目標是減少無效渲染、避免重復計算與狀態不一致。常見優化手段包括:
-
使用 React.memo:包裝函數組件,避免 props 無變化時重復渲染;
-
使用 useMemo:緩存復雜計算結果,僅在依賴變化時重新計算;
-
使用 useCallback:緩存函數引用,防止子組件因函數變化而重渲染;
-
避免匿名函數和 inline 對象:避免每次 render 創建新引用;
-
拆分組件粒度:將大組件拆分為小組件,提升局部更新效率;
-
懶加載(React.lazy + Suspense):按需加載組件,減少初始包體積;
-
虛擬滾動:使用 react-window、react-virtualized 等庫提升長列表渲染性能;
-
開啟生產構建優化:確保使用 production 模式打包,開啟 tree-shaking 和代碼壓縮。
- useMemo 和 useCallback 有什么區別?使用場景分別是什么?
答:
useMemo 與 useCallback 都用于性能優化,避免因重新渲染導致的重復計算或函數引用變更。
useMemo(fn, deps):返回 計算結果,常用于緩存變量(如復雜計算、篩選、排序等);
useCallback(fn, deps):返回 函數引用,常用于將函數傳入子組件或用于依賴中防止無限循環。
使用場景:
useMemo:優化計算型表達式;
useCallback:優化函數傳參與事件處理器。
需注意過度使用反而適得其反,建議僅在明顯性能瓶頸場景下使用。
- 什么是 Context?使用時有哪些注意事項?
答:
React Context 是用于跨組件層級共享數據的機制,適用于全局狀態傳遞如主題、用戶信息等。核心 API 包括:
const ThemeContext = React.createContext(defaultValue);
<ThemeContext.Provider value={…}>
</ThemeContext.Provider>
在子組件中使用 useContext(ThemeContext) 獲取上下文值。
注意事項:
每次 Provider 的 value 變化都會引發所有消費組件重新渲染;
可配合 useMemo 或分離 Provider 組件優化性能;
不適用于頻繁變化的局部狀態(如輸入框內容、臨時彈窗);
- React 中如何處理錯誤?如何實現錯誤邊界?
答:
React 提供錯誤邊界機制處理組件樹中的渲染錯誤(不包括事件、異步邏輯等)。
實現方法:
- 創建類組件,定義 componentDidCatch 和 getDerivedStateFromError:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
// 上報錯誤日志
}
render() {
return this.state.hasError ? : this.props.children;
}
}
- 使用方式:將其包裹目標組件
注意:錯誤邊界只能捕獲其子組件中的錯誤。
- React18 中的新特性有哪些?和之前版本有何不同?
答:
React 18 引入了多項新特性,提升并發渲染與用戶體驗能力:
-
自動批處理(Automatic Batching):多個 state 更新自動合并,減少 render 次數;
-
并發渲染架構(Concurrent Features):通過 startTransition 實現高優先級交互與低優先級更新并行處理;
-
Transition API:可區分緊急與非緊急更新,提升響應性能;
const [isPending, startTransition] = useTransition();
startTransition(() => {
setSearchQuery(input);
});
-
useId:解決 SSR 與客戶端 ID 不一致的問題;
-
ReactDOM.createRoot:替代 ReactDOM.render,支持并發模式;
-
Streaming SSR with Suspense:服務器端渲染支持 Suspense 流式輸出。
React 18 標志著進入“并發時代”,推薦逐步遷移核心項目使用新版能力。