函数组件与类组件
一、函数组件相关术语
纯函数(Pure Function)
同样的输入 → 永远相同的输出。不修改外部变量、不发请求、不操作 DOM——只做”根据输入算输出”这一件事。
# Python 纯函数:
def add(a, b):
return a + b # 只依赖参数,只返回结果,无副作用
# Python 不纯的函数:
total = 0
def add_to_total(x):
global total
total += x # 改了外部变量 total —— 不纯!
return total
React 要求函数组件的渲染阶段是纯函数:同样的 props + state → 同样的 UI。副作用(调 API、改全局变量、操作 DOM)必须放 useEffect 或事件处理器里。
副作用(Side Effect)
函数除了”根据输入算输出”之外,干的所有其他事情——调 API、操作 DOM、改全局变量、开定时器、订阅事件。
// 这些全是副作用:
fetch('/api/user') // ① 发网络请求
document.title = '新标题' // ② 操作 DOM
window.addEventListener('scroll', fn) // ③ 订阅全局事件
setTimeout(fn, 1000) // ④ 开定时器
console.log('xxx') // ⑤ 打印日志(也算!动了控制台)
localStorage.setItem('key', 'value') // ⑥ 写本地存储
生活比喻:副作用 = 做饭时的油烟、锅碗瓢盆的碰撞声、灶台的油渍。主菜(渲染 UI)是正事,但油烟(副作用)不可避免,只能放到**排风扇(useEffect)**里集中处理,不能满厨房到处飘。
高阶组件(HOC,Higher-Order Component)
一个函数,接收一个组件,返回一个新组件。本质是”组件包装器”——给组件增强能力,不修改原组件代码。
// HOC 模式:给任意组件加"权限检查"能力
function withAuth(WrappedComponent) { // 入参:一个组件
return function ProtectedComponent(props) { // 返回:一个新组件
if (!user.isLoggedIn) {
return <p>请先登录</p>; // 没登录 → 挡掉
}
return <WrappedComponent {...props} />; // 登录了 → 正常渲染
};
}
// 使用:
const ProtectedPage = withAuth(MyPage); // 包装一下,MyPage 就有权限检查了
HOC 的问题:多层 HOC 嵌套像俄罗斯套娃——withAuth(withLog(withTheme(MyComponent))),DevTools 里看到一坨。
函数组件时代的替代方案:自定义 Hook。不包装组件,直接在组件里调 const isAuth = useAuth()——更干净。
错误边界(Error Boundary)
一个特殊的类组件,用
componentDidCatch钩子捕获子组件渲染时抛出的错误,显示降级 UI(比如”出错了,请刷新”),防止整个页面白屏。
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error) { // 子组件崩了会走到这
this.setState({ hasError: true }); // 切换成降级 UI
}
render() {
if (this.state.hasError) {
return <h1>出错了,请刷新页面</h1>; // 降级 UI
}
return this.props.children; // 正常渲染子组件
}
}
函数组件目前不支持错误边界——只能用类组件实现。这是喜欢挖的一个细节。
StrictMode(严格模式)
React 的开发模式套件。包裹后会让组件渲染两次(帮你暴露出不纯的副作用),并在控制台打印额外警告。
<StrictMode>
<App />
</StrictMode>
// 开发环境下,所有组件函数会执行两遍
// 如果你在函数体里直接写了 fetch() → 发两次请求 → 你立刻发现不对劲
生产环境不生效。这就是为什么有时你
console.log会打印两次——不是 bug,是 StrictMode 在帮你体检。
速记卡(面试闪卡)
Q1:一句话讲清「函数组件与类组件」到底是什么?
A:React 函数组件与类组件及术语。
Q2:纯函数:同输入永远同输出 —— 怎么理解?
A:像计算器:同样按键永远同样结果,不偷偷改外部、不发请求。React 要求渲染阶段是 Pure Function(纯函数)——props+state 进,UI 出;副作用(调 API、改全局)必须赶进排风扇 useEffect,不能满厨房飘。
Q3:副作用:渲染之外的那些事 —— 怎么理解?
A:像做饭的油烟:发请求、改 DOM、开定时器、写 localStorage 全算 Side Effect(副作用)。主菜(渲染 UI)是正事,油烟只能塞进排风扇 useEffect 集中处理,不能散在组件各处——否则 StrictMode 渲染两遍就露馅。
Q4:HOC:组件包组件加能力 —— 怎么理解?
A:像套娃外壳:withAuth(MyPage) 接收组件返回加了权限检查的新组件,不改动原代码。本质是 Higher-Order Component(高阶组件),但多层嵌套像俄罗斯套娃;函数组件时代改用自定义 Hook 更干净。
Q5:错误边界与严格模式 —— 怎么理解?
A:像安全网:Error Boundary(错误边界)是特殊类组件,用 componentDidCatch 兜住子组件崩溃显示降级 UI,防止白屏——函数组件目前做不了,只能靠类组件。StrictMode(严格模式)开发期让组件渲染两遍,专抓不纯副作用。
Q6:核心速记主线有哪些?
-
渲染要纯函数无副作用
-
副作用塞进 useEffect
-
HOC 包装增强可换 Hook
-
错误边界仅类组件能做
口诀
A:渲染要纯函数,副作用进 useEffect
油烟不能满屋飘,排风扇里集中消
HOC 套娃能加料,自定义 Hook 更轻巧
错误边界类组件,StrictMode 双渲染挑