原文發表於Medium
React是2025 年前端開發人員最需要的技能之一。如果您正在準備2025 年的React開發人員面試,那麼掌握最新的最佳實踐、模式和概念至關重要。
本文列出了17 個 React 面試問題,涵蓋了從核心React原則到高階效能優化的所有內容,可協助您在下一次React開發人員面試中脫穎而出。
讓我們開始吧!
虛擬 DOM是一種概念,其中真實 DOM的虛擬表示保存在記憶體中,並且僅在必要時透過ReactDOM等函式庫與實際DOM同步。
虛擬DOM是記憶體中代表真實DOM的物件。由於DOM更新是任何 Web 應用程式不可或缺的一部分,但卻是前端開發中最昂貴的操作,因此虛擬 DOM用於檢查應用程式需要更新的部分並僅更新這些部分,從而顯著提高效能。
虛擬 DOM與真實 DOM和影子 DOM是完全不同的概念。真實 DOM是HTML 文件在樹狀結構中的實際表示,瀏覽器使用它來追蹤網頁的內容,而Shadow DOM是一種程式設計實踐,允許開發人員為 Web 應用程式建立獨立的可重複使用元件。
如果你想深入了解虛擬 DOM 、真實 DOM和影子 DOM之間的區別,請查看 這篇文章
React中有兩種類型的元件:
類別元件
功能元件
以前,類別元件是建立具有React中任何功能的元件的唯一方法,而功能元件僅用作展示元件,通常被稱為“啞”元件。
但是,隨著React 16.8的發布和React Hooks的引入,函數式元件現在可以擁有狀態和生命週期方法,使它們成為在React中建立元件的首選方式。
功能元件比類元件速度快得多,而且開銷和樣板程式碼更少,因此建議盡可能使用功能元件。但是某些生命週期方法仍然僅在類別元件中可用,因此您可能需要在某些特殊情況下使用類別元件,例如建立自訂錯誤邊界(例如:在類別元件中使用componentDidCatch
生命週期方法)。
React中的Keys
用於辨識唯一的虛擬 DOM 元素及其驅動UI 的相應資料。使用keys
有助於React透過回收現有的DOM 元素來優化渲染。
Keys
可協助React辨識哪些專案已變更、新增或刪除,使其能夠重複使用已經存在的DOM 元素,從而提高效能。
例如:
const Todos = ({ todos }) => {
return (
<div>
{todos.map((todo) => (
<li>{todo.text}</li>
))}
</div>
);
};
這將導致每次待辦事項更改時都會建立新的DOM 元素,但新增key
prop(即: <li key={todo.id}>{todo.text}</li>
)將導致「拖曳」 ul
標籤內的DOM 元素並僅更新必要的li
Keys
可以與React中的任何元素一起使用,並且不一定需要與列表一起使用,但它最常用於列表以優化渲染。一些非標準(&不建議)的keys
用例包括使用它們強制重新渲染元件,如下例所示:
const TimeNow = () => {
const [key, setKey] = useState(0);
useEffect(() => {
const interval = setInterval(() => setKey((prevKey) => prevKey + 1), 1000);
return () => clearInterval(interval);
}, []);
return <div key={key}>{new Date()}</div>;
};
如上所述,絕對應該避免使用這樣的程式碼,並且最好使用狀態來儲存時間,而不是使用鍵來強制重新渲染。使用keys
強制重新渲染是一種反模式,可能會導致嚴重的效能問題,除非您確切知道自己在做什麼。
受控元件依賴React 狀態來管理表單資料,而非受控元件使用DOM本身來處理表單資料。
在大多數情況下,受控元件是首選,因為它們為表單資料提供了單一真實來源,從而更易於管理、驗證和提交表單資料。
const ControlledInputForm = () => {
const [value, setValue] = useState("");
const handleChange = (e) => setValue(e.target.value);
const handleSubmit = (e) => {
e.preventDefault();
console.log(value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={value} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
};
const UncontrolledInputForm = () => {
const inputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} />
<button type="submit">Submit</button>
</form>
);
};
除非你傷到了頭,否則你不會像這樣使用React :
import { createElement } from "react";
const Greeting = ({ name }) => {
return createElement("h1", { className: "greeting" }, "Hello");
};
然而,這就是瀏覽器讀取的內容——它根本無法理解通常用於編寫React 元件的JSX 語法。
因此我們需要使用Babel之類的工具將JSX 轉換為JavaScript ,以便瀏覽器可以執行它。因此當你編寫以下程式碼時:
const Greeting = ({ name }) => <h1 className="greeting">Hello</h1>;
它被轉換為前面的程式碼片段,以便瀏覽器可以解釋它並呈現元件。
由於JSX將內容呈現為文本,因此使用者輸入的任何元素都不會被視為HTML ,而只是純文本。例如,以下script
標籤將被呈現為文字並且不會執行:
const MyComponent = () => {
const content = "<script>alert('XSS')</script>";
return <div>{content}</div>;
};
注意:您可以使用dangerouslySetInnerHTML
覆寫此行為,但不建議這樣做,除非您絕對確定輸入的來源(並且強烈建議在註入之前清理內容)。
const MyComponent = () => {
const content = "<script>alert('XSS')</script>";
return <div dangerouslySetInnerHTML={{ __html: content }} />;
};
使用CSS檔案是設定React 元件樣式的最常用方法之一。它允許使用所有CSS功能,並且預設使用Create React App設定。
/* Button.css */
.button {
background-color: blue;
color: white;
}
// Button.tsx
import "./Button.css";
const Button = () => {
return <button className="button">Click me</button>;
};
使用內聯CSS對React 元素進行樣式設定可將樣式完全限定在元素範圍內。但是,內聯樣式不提供某些樣式功能。例如,像:hover
這樣的偽類的樣式。
const Button = () => {
return (
<button style={{ backgroundColor: "blue", color: "white" }}>
Click me
</button>
);
};
CSS-in-JS模組是設計React 應用程式樣式的熱門選擇,因為它們與React 元件緊密整合。例如,它們允許樣式在執行時根據React props進行更改。此外,預設情況下,大多數系統會將所有樣式限定在對應的被設定樣式的元件內。
import styled from "styled-components";
const Button = styled.button`
background-color: blue;
color: white;
`;
const App = () => {
return <Button>Click me</Button>;
};
我個人最喜歡的樣式方法, CSS 模組允許將樣式限定在單一元件內。這是避免類別名稱衝突(指兩個類別最終具有相同名稱的術語 - 在大型專案中很常見)、保持樣式井然有序以及向多個元件加入共用樣式的好方法。
/* Button.module.css */
.button {
background-color: blue;
color: white;
}
// Button.js
import styles from "./Button.module.css";
const Button = () => {
return <button className={styles.button}>Click me</button>;
};
合成事件將不同瀏覽器原生事件的回應組合成一個 API ,確保事件在不同瀏覽器之間保持一致。無論在哪種瀏覽器中執行,應用程式都是一致的。
const Component = () => {
const handleClick = (e) => {
e.preventDefault(); // synthetic event
console.log("link clicked");
};
return <a onClick={(e) => handleClick}>Click me</a>;
};
<StrictMode />
是React附帶的一個元件,用於提供元件中潛在問題的額外可見性。如果應用程式在開發模式下執行,則出現的任何問題都會記錄到開發控制台,但如果應用程式在生產模式下執行,則不會顯示這些警告。
開發人員使用<StrictMode />
來尋找諸如棄用的生命週期方法和遺留模式等問題,以確保所有React 元件都遵循當前的最佳實踐。
<StrictMode />
可以應用於應用程式元件層次結構的任何級別,這允許它在程式碼庫中逐步採用。
<StrictMode />
的文件新增如下
嚴格模式支援以下僅限開發的行為:
>
您的元件將重新渲染一次,以查找不純渲染引起的錯誤。
您的元件將額外重新執行效果以查找因缺少效果清理而導致的錯誤。
您的元件將額外重新執行 refs 回呼以尋找因缺少 ref 清理而導致的錯誤。
您的元件將被檢查是否使用了棄用的 API 。
預設情況下,如果React 應用程式在渲染期間拋出錯誤, React將從螢幕上刪除其 UI。為了防止這種情況,我們可以將 UI 的一部分包裝到錯誤邊界中,這樣我們就可以捕獲錯誤並顯示後備 UI ,而不是導致整個應用程式崩潰。
您可以建立自訂錯誤邊界:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI, or even accept it as a prop
return <FallbackComponent />;
}
return this.props.children;
}
}
但在大多數情況下,您可以使用react-error-boundary
包,它提供了處理React 應用程式中的錯誤所需的元件。
import { ErrorBoundary } from "react-error-boundary";
const App = () => (
<ErrorBoundary FallbackComponent={FallbackComponent}>
<MyComponent />
</ErrorBoundary>
);
React Hooks有 3 個主要規則:
僅從 React 函數呼叫鉤子:鉤子只能在React 函數元件內或另一個鉤子內呼叫。在常規JS / TS函數中呼叫鉤子將被視為常規函數呼叫,並且不會按預期工作。
僅在頂層呼叫鉤子:鉤子只能在React 函數元件或自訂鉤子的頂層呼叫。這是為了確保每次元件渲染時都按照相同的順序呼叫鉤子。在循環、條件或巢狀函數中使用鉤子將導致錯誤。
鉤子必須以“use”開頭:所有鉤子名稱(包括自訂鉤子)必須以單字“use”開頭。這是為了確保React能夠辨識鉤子並強制執行鉤子的規則。例如useState
、 useEffect
、 useContext
等。
React中常見的生命週期方法有:
componentDidMount
:元件安裝到DOM上後呼叫。通常用於取得資料或執行副作用,如新增事件監聽器。
componentDidUpdate
:在元件中的某些特定值更新後呼叫。通常用於根據更新的值執行副作用。
componentWillUnmount
:在元件從DOM卸載之前呼叫的清理方法。通常用於刪除事件監聽器或取消網路請求。
在功能元件中,可以使用useEffect
鉤子來處理這些生命週期方法。 useEffect
鉤子將函數作為其第一個參數,將依賴項陣列作為其第二個參數。
const Component = () => {
useEffect(() => {
// componentDidMount
console.log("Component mounted");
return () => {
// componentWillUnmount
console.log("Component unmounted");
};
}, []); // empty dependency array implies this effect runs only once when the component mounts
useEffect(
() => {
// componentDidUpdate
console.log("Component updated");
},
[
/* dependencies - changes to these values should trigger the function to re-run */
/* NOTE: This function will run during mount too */
]
);
return <React.Fragment />;
};
Refs
是允許您在渲染之間保留資料的變數,就像state
變數一樣,但與state
變數不同的是,更新refs
不會導致元件重新渲染。
Refs
通常用於(但不限於)儲存DOM 元素的參考。
const Component = () => {
const inputRef = useRef(null);
const handleClick = () => inputRef.current.focus();
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus Input</button>
</div>
);
};
在開發React 應用程式時,經常需要將資料從層次結構中較高的元件傳遞到深度嵌套的元件。 Prop 鑽取是指將props從來源元件經由所有中間元件傳遞到深層嵌套元件的過程。
使用prop 鑽取的缺點是,原本不應該知道資料的元件可以存取資料,而且程式碼變得更難維護。
可以使用Context API或某種形式的狀態管理庫來避免Prop 鑽取。
useMemo
是一個React hook ,用來快取耗費 CPU 的函數。由於元件重新渲染而重複呼叫耗費 CPU 的函數可能會導致嚴重的效能問題和使用者體驗下降。
useMemo
鉤子可用於快取此類函數的結果。透過使用useMemo
,僅在需要時才呼叫CPU-Expensive 函數。
延遲載入是一種用於減少React 應用程式初始載入時間的技術。透過在使用者瀏覽應用程式時載入元件,它有助於將 Web 應用程式效能的風險降至最低。
雖然這不是React 特有的優化技術,但它經常在React 應用程式中用於提高效能。節流和去抖是用於限制回應事件而呼叫函數的次數的技術 - 它們通常與向使用者提供即時回饋的輸入一起使用(例如:在具有自動建議的搜尋欄位中輸入 - 可以對獲取建議的API 呼叫進行節流或去抖,以避免進行不必要的API 呼叫)
Portal是一種建議的方法,用於將子專案渲染到父元件DOM 層次結構之外的DOM 節點。建議為入口網站建立一個新的DOM 節點。
const Portal = ({ children }) => {
// NOTE: it is assumed that the portal root is already present in the HTML file
// <div id="portal-root" />
const portalRoot = document.getElementById("portal-root");
return ReactDOM.createPortal(children, portalRoot);
};
React Fiber是ReactJS的一個概念,用於更快、更流暢地渲染系統。這是一次內部引擎的改變,旨在讓React更快、更「智慧」 。 Fiber 協調器已成為React 16及更高版本的預設協調器,它是對React 協調演算法的完全重寫,以解決React中一些長期存在的問題。
由於Fiber是異步的,因此React可以:
隨著新更新的到來,暫停、恢復和重新啟動元件的渲染工作
重複使用先前完成的工作,甚至在不需要時中止它
將工作分成多個部分,並根據重要性決定任務的優先級
這個改變使得React擺脫了先前同步Stack Reconciler的限制,即任務無法被打斷。這項變更還允許React微調渲染元件,確保最重要的更新盡快發生。
您是否正在摸不著頭腦,不明白「和解」到底是什麼?
別擔心,我們會保護您的!在React中,協調是負責根據元件狀態或 props 的變化有效更新UI 的核心機制。它確定了轉換實際DOM以匹配虛擬 DOM所表示的所需狀態所需的最小操作集。
就這樣吧,夥計們! 🎉
如果你想要一份React Native面試題列表,請繼續關注下一篇文章!
需要一位頂級軟體開發自由工作者來解決您的開發難題嗎?在Upwork上聯絡我
想要連接嗎?透過LinkedIn聯絡我
關注我的博客,每兩週在Medium上獲取最新資訊
常問問題
這些是我收到的一些常見問題。因此,我希望此常見問題解答部分能夠解決您的問題。
請參考以下文章:
您能指導我嗎?
抱歉,我的工作量已經很重了,沒有時間指導任何人。
原文出處:https://dev.to/ruppysuppy/17-react-interview-questions-you-must-know-as-a-developer-in-2025-1o6f