React全部api解读|原理篇
30 秒速记
- 核心判断:理解原理要建立输入、状态变化、输出和失败边界,而不是只记 API 与结论
- 原理主线:围绕 「组件类」、「工具类」、「react-hooks」 建立输入、状态变化与输出之间的因果关系
- 文章范围:系统梳理了 React 的全部核心 API,包括组件类(Component、PureComponent)、内置组件(Fragment、StrictMode)、高阶组件(forwardRef、memo)等,详细解析每个 API 的原理、用法及
- 边界与代价:文章中的实现通常有版本和场景前提,迁移到当前项目时必须先核对运行环境与依赖
- 工程落地:面试回答按核心机制、执行链路、边界反例和工程验证展开,最后说明取舍
React 的 API 本质上是在控制组件描述、更新边界和渲染时机,不能只记调用方式。 比如 PureComponent 浅比较 props 与 state,React.memo 只比较 props,而自定义比较函数返回 true 反而表示跳过渲染。forwardRef 用于转发特殊处理的 ref,lazy 通常配合 Suspense 处理异步组件。涉及旧生命周期或 ReactDOM.render 时,还要区分历史实现与当前版本行为。
这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。
版本校准: 本文若分析 ReactDOM.render、旧生命周期或栈调和,应把它视为理解架构演进的历史路径。React 19 已移除 ReactDOM.render,当前客户端入口使用 createRoot;并发渲染也必须区分可中断的渲染阶段与同步提交阶段。迁移前对照 React 19 官方升级指南。
# 组件类
组件类,详细分的话有三种类,第一类说白了就是我平时用于继承的基类组件Component,PureComponent,还有就是react提供的内置的组件,比如Fragment,StrictMode,另一部分就是高阶组件forwardRef,memo等。

# Component
Component是class组件的根基。类组件一切始于Component。对于React.Component使用,我们没有什么好讲的。我们这里重点研究一下react对Component做了些什么。
react/src/ReactBaseClasses.js
function Component(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
这就是Component函数,其中updater对象上保存着更新组件的方法。
我们声明的类组件是什么时候以何种形式被实例化的呢?
react-reconciler/src/ReactFiberClassComponent.js
constructClassInstance
function constructClassInstance(
workInProgress,
ctor,
props
){
const instance = new ctor(props, context);
instance.updater = {
isMounted,
enqueueSetState(){
/* setState 触发这里面的逻辑 */
},
enqueueReplaceState(){},
enqueueForceUpdate(){
/* forceUpdate 触发这里的逻辑 */
}
}
}
对于Component, react 处理逻辑还是很简单的,实例化我们类组件,然后赋值updater对象,负责组件的更新。然后在组件各个阶段,执行类组件的render函数,和对应的生命周期函数就可以了。
# PureComponent
PureComponent和 Component用法,差不多一样,唯一不同的是,纯组件PureComponent会浅比较,props和state是否相同,来决定是否重新渲染组件。所以一般用于性能调优,减少render次数。
什么叫做浅比较,我这里举个列子:
class Index extends React.PureComponent{
constructor(props){
super(props)
this.state={
data:{
name:'alien',
age:28
}
}
}
handerClick= () =>{
const { data } = this.state
data.age++
this.setState({ data })
}
render(){
const { data } = this.state
return <div className="box" >
<div className="show" >
<div> 你的姓名是: { data.name } </div>
<div> 年龄: { data.age }</div>
<button onClick={ this.handerClick } >age++</button>
</div>
</div>
}
}
)
点击按钮,没有任何反应,因为PureComponent会比较两次data对象,都指向同一个data,没有发生改变,所以不更新视图。
解决这个问题很简单,只需要在handerClick事件中这么写:
this.setState({ data:{...data} })
浅拷贝就能根本解决问题。
# memo
React.memo和PureComponent作用类似,可以用作性能优化,React.memo 是高阶组件,函数组件和类组件都可以使用, 和区别PureComponent是 React.memo只能对props的情况确定是否渲染,而PureComponent是针对props和state。
React.memo 接受两个参数,第一个参数原始组件本身,第二个参数,可以根据一次更新中props是否相同决定原始组件是否重新渲染。是一个返回布尔值,true 证明组件无须重新渲染,false证明组件需要重新渲染,这个和类组件中的shouldComponentUpdate()正好相反 。
React.memo: 第二个参数 返回 true 组件不渲染 , 返回 false 组件重新渲染。 shouldComponentUpdate: 返回 true 组件渲染 , 返回 false 组件不渲染。
接下来我们做一个场景,控制组件在仅此一个props数字变量,一定范围渲染。
例子🌰:
控制 props 中的 number :
- 1 只有
number更改,组件渲染。 - 2 只有
number小于 5 ,组件渲染。
function TextMemo(props){
console.log('子组件渲染')
if(props)
return <div>hello,world</div>
}
const controlIsRender = (pre,next)=>{
if(pre.number === next.number ){ // number 不改变 ,不渲染组件
return true
}else if(pre.number !== next.number && next.number > 5 ) { // number 改变 ,但值大于5 , 不渲染组件
return true
}else { // 否则渲染组件
return false
}
}
const NewTexMemo = memo(TextMemo,controlIsRender)
class Index extends React.Component{
constructor(props){
super(props)
this.state={
number:1,
num:1
}
}
render(){
const { num , number } = this.state
return <div>
<div>
改变num:当前值 { num }
<button onClick={ ()=>this.setState({ num:num + 1 }) } >num++</button>
<button onClick={ ()=>this.setState({ num:num - 1 }) } >num--</button>
</div>
<div>
改变number: 当前值 { number }
<button onClick={ ()=>this.setState({ number:number + 1 }) } > number ++</button>
<button onClick={ ()=>this.setState({ number:number - 1 }) } > number -- </button>
</div>
<NewTexMemo num={ num } number={number} />
</div>
}
}
效果:

完美达到了效果,React.memo一定程度上,可以等价于组件外部使用shouldComponentUpdate ,用于拦截新老props,确定组件是否更新。
# forwardRef
官网对forwardRef的概念和用法很笼统,也没有给定一个具体的案例。很多同学不知道 forwardRef具体怎么用,下面我结合具体例子给大家讲解forwardRef应用场景。
1 转发引入Ref
这个场景实际很简单,比如父组件想获取孙组件,某一个dom元素。这种隔代ref获取引用,就需要forwardRef来助力。
function Son (props){
const { grandRef } = props
return <div>
<div> i am alien </div>
<span ref={grandRef} >这个是想要获取元素</span>
</div>
}
class Father extends React.Component{
constructor(props){
super(props)
}
render(){
return <div>
<Son grandRef={this.props.grandRef} />
</div>
}
}
const NewFather = React.forwardRef((props,ref)=><Father grandRef={ref} {...props} /> )
class GrandFather extends React.Component{
constructor(props){
super(props)
}
node = null
componentDidMount(){
console.log(this.node)
}
render(){
return <div>
<NewFather ref={(node)=> this.node = node } />
</div>
}
}
效果

