React中RCC与RFC的区别及类组件与函数组件适用场景咨询
React类组件(RCC)与函数组件的区别及适用场景
一、RCC与函数组件的核心区别
注:你可能笔误将「类组件(RCC,React Class Component)与函数组件」写成了两个RCC,以下是二者的核心差异:
定义方式不同
- 类组件:基于ES6类实现,必须继承
React.Component或React.PureComponent,且必须包含render()方法返回JSX结构。class UserCard extends React.Component { render() { return <div className="card">{this.props.username}</div>; } } - 函数组件:以普通JavaScript函数形式定义,直接返回JSX,早期仅支持无状态展示,现在通过Hooks可实现完整的状态与副作用管理。
function UserCard({ username }) { return <div className="card">{username}</div>; }
- 类组件:基于ES6类实现,必须继承
状态管理逻辑不同
- 类组件:通过
this.state存储状态,依赖this.setState()更新,更新操作异步,支持传入函数处理依赖前状态的更新逻辑。class Counter extends React.Component { state = { count: 0 }; addCount = () => { this.setState(prevState => ({ count: prevState.count + 1 })); }; render() { return <button onClick={this.addCount}>{this.state.count}</button>; } } - 函数组件:使用
useState、useReducer等Hooks管理状态,useState直接返回状态值和更新函数,语法更简洁直观。function Counter() { const [count, setCount] = useState(0); const addCount = () => setCount(prev => prev + 1); return <button onClick={addCount}>{count}</button>; }
- 类组件:通过
生命周期与副作用处理不同
- 类组件:拥有独立的生命周期钩子,如
componentDidMount(挂载完成)、componentDidUpdate(更新完成)、componentWillUnmount(卸载前),用于处理数据请求、事件监听等副作用。class DataLoader extends React.Component { componentDidMount() { fetch('/api/user') .then(res => res.json()) .then(data => this.setState({ user: data })); } componentWillUnmount() { // 清理未完成的请求 this.abortController?.abort(); } render() { return <div>{this.state.user?.name}</div>; } } - 函数组件:通过
useEffectHook模拟生命周期,一个useEffect可对应多个类组件钩子的组合,通过依赖数组控制执行时机,返回的函数用于清理副作用。function DataLoader() { const [user, setUser] = useState(null); useEffect(() => { const abortController = new AbortController(); fetch('/api/user', { signal: abortController.signal }) .then(res => res.json()) .then(data => setUser(data)); // 清理函数,对应componentWillUnmount return () => abortController.abort(); }, []); // 空依赖数组仅在挂载时执行 return <div>{user?.name}</div>; }
- 类组件:拥有独立的生命周期钩子,如
this指向问题
- 类组件:类方法中的
this需要手动绑定(构造器绑定、箭头函数定义方法等),否则会指向undefined。 - 函数组件:不存在
this指向问题,所有变量和方法都处于函数作用域内,无需额外绑定。
- 类组件:类方法中的
性能优化方式不同
- 类组件:通过继承
React.PureComponent或实现shouldComponentUpdate钩子,浅比较props和state来避免不必要的重渲染。 - 函数组件:使用
React.memo包裹组件实现浅比较优化,配合useMemo缓存计算结果、useCallback缓存函数,避免子组件无意义重渲染。
- 类组件:通过继承
二、适用场景举例
优先使用类组件的场景
- 维护遗留类组件项目:如果项目中已有大量稳定运行的类组件,无需强行重构为函数组件,继续使用类组件维护可避免迁移成本。
- 依赖类组件独有API:比如需要使用
getSnapshotBeforeUpdate(获取更新前DOM快照)、componentDidCatch(捕获子组件错误)等函数组件暂未完全替代的API时。 - 团队技术栈适配:如果团队成员对类组件的开发、调试更熟悉,为保证开发效率和代码一致性,可继续使用类组件。
优先使用函数组件的场景
- 简单UI展示组件:如按钮、标签、列表项等无复杂状态和副作用的组件,函数组件代码更简洁,可读性更高。
function Tag({ text, color }) { return <span className={`tag tag-${color}`}>{text}</span>; } - 需要复用逻辑的场景:通过自定义Hooks可将组件逻辑(如数据请求、状态管理、事件监听)抽离复用,相比类组件的高阶组件、mixin更灵活。
- 示例:自定义获取滚动位置的Hook
function useScrollPosition() { const [pos, setPos] = useState({ x: 0, y: 0 }); useEffect(() => { const handleScroll = () => setPos({ x: window.scrollX, y: window.scrollY }); window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, []); return pos; } // 在组件中直接使用 function ScrollTracker() { const { y } = useScrollPosition(); return <div>当前滚动位置:{y}px</div>; }
- 示例:自定义获取滚动位置的Hook
- 新项目开发:函数组件配合Hooks的组合式编程模式,代码结构更清晰,更符合React官方的推荐方向,适合新项目选型。
内容的提问来源于stack exchange,提问作者ROSBY ASIAMAH
相关产品推荐
相关产品推荐

