学会在面试里不绕弯地解释 React Hooks。
很多初级候选人挂在 React 面试上,并不是不会 Hooks,而是在压力下讲不清楚。
这篇文章用模拟真实对话的方式,帮你看到:不仅是“答什么”,更是“怎么自信又清楚地表达”。
场景:前端开发面试
面试官是一位资深前端,刚刚问到:React Hooks。
回合 1:向非技术同事解释 Hooks
Interviewer:“别太技术化,你能解释一下 React Hooks 吗?”
Candidate:“Hooks 像是把超能力赋给函数组件。以前管理状态和生命周期要用 class 组件;有了 Hooks,我们能在函数里处理状态、副作用与逻辑复用——组件因此更简洁、干净、易共享。”
回合 2:基础入门 —— useState
Interviewer:“用最简单的话说,useState 是什么?”
Candidate:“它让组件在多次渲染之间记住数据。比如计数器:”
import React, { useState } from “react”;
function Counter() {
const [count, setCount] = useState(0);
return (
You clicked {count} times setCount(count + 1)}>Click Me
);
}
每次调用 setCount,React 都会用更新后的值重新渲染。
回合 3:副作用 —— useEffect
Interviewer:“什么时候用 useEffect?”
Candidate:“当你要在渲染之后做事时,比如拉取数据或手动更新 DOM。”
import React, { useState, useEffect } from “react”;
function FetchUser() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(“https://jsonplaceholder.typicode.com/users/1”)
.then(res => res.json())
.then(data => setUser(data));
}, []); // 仅首渲染运行一次
return
{user ? user.name : “Loading…”};
}
⚠️ 注意:依赖数组写错会导致无限循环。
好的 👍——我们继续精炼、清晰、对初学者友好(保留代码)。下面用同样的问答方式进入 Round 4:共享数据 —— useContext。
回合 4:共享数据 —— useContext
Interviewer:“useContext 的作用?”
Candidate:“避免层层传 props(prop drilling)。把树包装在一个 Provider 里,任意后代用 useContext 就能直接读写。”
import React, { createContext, useContext, useState } from “react”;
// 1) 创建上下文
const ThemeContext = createContext<{ theme: string; setTheme: (t: string) => void } | null>(null);
// 2) Provider
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState(“light”);
return (
{children}
);
}
// 3) Consumer
function ThemedButton() {
const ctx = useContext(ThemeContext)!;
const { theme, setTheme } = ctx;
return (
setTheme(theme === “light” ? “dark” : “light”)}> Current theme: {theme}
);
}
// 用法
export default function App() {
return (
);
}
要点
解决什么:告别一层层重复传同一个 prop。
适合场景:主题、登录态、语言环境等全局状态。
潜在问题:上下文值频繁变化会让所有消费者一起重渲染。
另一种更轻量的演示:
import React, { createContext, useContext } from “react”;
const ThemeContext = createContext(“light”);
function ThemedButton() {
const theme = useContext(ThemeContext);
return I’m styled with {theme} theme;
}
function App() {
return (
);
}
回合 5:复杂状态 —— useReducer
Interviewer:“useReducer 比 useState 更好吗?”
Candidate:“当状态更新有多步骤/多分支时,useReducer 更清晰、可维护。”
import React, { useReducer } from “react”;
type State = { count: number };
type Action = { type: “increment” } | { type: “decrement” };
function reducer(state: State, action: Action): State {
switch (action.type) {
case “increment”: return { count: state.count + 1 };
case “decrement”: return { count: state.count – 1 };
default: return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
{state.count}
dispatch({ type: “increment” })}>+
dispatch({ type: “decrement” })}>-
);
}
回合 6:useRef
Interviewer:“useRef 做什么?”
Candidate:“它能存放可变值且不触发重渲染;同时也常用于拿到 DOM 引用。”
import React, { useRef, useEffect } from “react”;
function InputFocus() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return ;
}
回合 7:性能相关 —— useMemo & useCallback
Interviewer:“怎么用 Hooks 做性能优化?”
Candidate:
useMemo:缓存昂贵计算的结果
useCallback:缓存函数,避免子组件无谓重渲染
import React, { useState, useMemo, useCallback } from “react”;
function ExpensiveComponent({ value }: { value: number }) {
const calc = useMemo(() => {
console.log(“Heavy calculation running…”);
return value * 2;
}, [value]);
return
Calculated: {calc};
}
function Parent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount(c => c + 1), []);
return (
<>
+
);
}
回合 8:useLayoutEffect
Interviewer:“useLayoutEffect 和 useEffect 有什么不同?”
Candidate:“useEffect 在浏览器完成绘制后执行;useLayoutEffect 在绘制前同步运行。需要读取布局并在用户看到前完成调整时,用 useLayoutEffect。”
import React, { useRef, useLayoutEffect } from “react”;
function Box() {
const boxRef = useRef(null);
useLayoutEffect(() => {
console.log(“Box width:”, boxRef.current?.offsetWidth);
}, []);
return
;
}
📝 面试速记
useState = 组件的“记忆”
useEffect = 渲染后的任务
useContext = 免 prop-drilling
useReducer = 复杂状态流
useRef = 可变值/DOM 引用,不触发重渲染
useMemo & useCallback = 结果/函数缓存,减少无谓渲染
useLayoutEffect = 绘制前读写布局
👉 不只给定义,还要说类比与取舍。
简历要点(Hooks 相关)
使用 useState / useEffect / useContext 封装可复用组件,减少样板代码约 30%。
结合 useMemo / useCallback 优化渲染路径,降低不必要重渲染约 25%。
编写 自定义 Hooks 统一请求/缓存逻辑,在 10+ 个组件中复用。
将 class 组件迁移到 Hooks,简化生命周期管理与状态流转。
用 useReducer 管理复杂表单与业务状态,提升可维护性。
最后:
20个前端开发者必备的响应式布局
深入React:从基础到最佳实践完整攻略
python 技巧精讲
React Hook 深入浅出
CSS技巧与案例详解
vue2与vue3技巧合集
声明:来自JavaScript 每日一练,仅代表创作者观点。链接:https://eyangzhen.com/3293.html