函数组件与类组件

一、函数组件相关术语

纯函数(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 双渲染挑

相关链接