setState
同步还是异步的,很多前端都回答是异步的,这样面试官觉得没有新意。怎么回答会让面试官眼前一亮呢?
🤖 我为什么说 setState
为什么是同步的呢?
因为 setState
他确实是一个同步函数啊。他嗖的一下就执行完了,只不过他安排了一个异步任务
这也是许多前端新人前期学 react
常常踩的一个坑,只不过还有前端新人吗?😭
接下来我将给你们进行一波
react
源码级别的企业级讲解
🤖 setState
你在赣什么?
function App() {
const [state, setState] = useState('三和大神')
function handleClick() {
setState('许泽川')
console.log(state)
}
return <div onClick={handleClick}>{state}</div>
}
- 在不同的地方调用
setState
,会创建不同优先级的更新。比如这里在点击事件里面触发,会创建一个优先级为1
的许泽川
的更新 - 根据更新的优先级,通过宏任务或者微任务注册一个任务。 这个任务就是:触发重渲染,通过这个新的
许泽川
更新创建出新的App Fiber
。
有的急性子, setState
完就想拿来用,发现,咋还是三和大神。
setState
: 我值都还没改,服吗?😈
🤖 小贴士
🚀 优先级
抄袭浏览器的事件优先级
-
React
一共有4
种优先级,从高到低是离散事件点击
、连续事件输入、滚动
、默认事件、空闲事件 -
32位二进制切成四个部分,给四种优先级分,离散事件
1车道
、连续事件01车道001车道
、默认事件0001车道
、空闲事件剩下的车道都归我
-
每次
setState
会判断当前上下文拿一个车道出来,创建一个车道对应优先级的更新,和对应优先级的重渲染任务来处理这个更新 -
离散事件优先级最高,通过微任务
queueMicrotask
执行重渲染。连续事件默认事件空闲事件全部通过宏任务MessageChannel
执行重渲染
todo 空闲事件时间切片
🚀 批量渲染
在同一个地方 setState
多次,说明他有相同的优先级
源码有一个条件语句,只要发现是相同的优先级,函数就 return
了 也就是只有第一次的 setState
安排了一个重渲染任务,之后的 setState
都跳过了
function 重渲染() {
if (新的优先级 === 当前的优先级) return;
根据当前 setState 的优先级,通过宏任务或者微任务注册一个重渲染任务
}
计算顺序不会出错
就是说啊,我们上面不是提了优先级嘛。那其实高优先级的 setState
能打断低优先级的 这个说来话长一时半会讲不清楚
比如现在 const [state, setState] = useState('许泽川')
然后我们在低优先级的上下文中,setState(state => state + '不是')
还没重渲染的时候,我们又在高优先级的上下文中,setState(state => state + '帅哥')
-
那么他会打断低优先级的,先处理高优先级的
setState
,变成许泽川帅哥
-
然后再处理低优先级的
setState
,变成许泽川帅哥不是
-
错了,是变成
许泽川不是帅哥
😠why,u tripping?
setState
执行了两次创建了 2 个不同优先级的 update
- 本来好好的,低优先级的
setState
执行,这时候的更新链条就只有他本身,也就是,内容就是在许泽川
后面加不是
- 这时候高优先级的来了,低优先级被打断,这时候的更新链条就变成了
低优先级的 update:state => state + '不是'
------>高优先级的 update:state => state + '帅哥'
,然后应用更新,但是他只会更新当前优先级和优先级比他高的update
,所以低优先级的update
没有更新,所以变成了许泽川帅哥
- 所以说低优先级的
update
是没有更新的,他被跳过了,但是会把跳过本身和他之后的链表保存起来,还会把这条链表更新前的值保存起来。也就是保存了 更新链表:跳过的低优先级的 update:state => state + '不是'
->高优先级的 update:state => state + '帅哥'
更新前的值:许泽川
- 高优先级的更新后,重渲染完成之后呢。
react
又会判断还有没有优先级,如果有又会重新触发一次重渲染。发现确实有一个低优先级的车道在等着。那这次就进行低优先级的重渲染,同样他会更新当前优先级和优先级比他高的update
,所以低优先级和高优先级的更新这一次都应用到了 更新前的值:许泽川
上,所以变成了许泽川+不是+帅哥
小优化:eagerState
先赊个账,文章先发了,这个找到工作再补充
🤖 相关
面试官:你说你做过组件库,肯定了解过复杂组件状态管理的useSyncExternalStore吧?我:😭
面试官:你跟我说 setState 是同步的,它不是异步的吗?背错面试题了吧你!我:😭
面试官:你说你开发过组件库,那你怎么会不知道受控组件?面试就到这里吧。我:😭
版权归许泽川所有
如需转载,请提前询问本人的许可