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 是同步的,它不是异步的吗?背错面试题了吧你!我:😭
面试官:你说你开发过组件库,那你怎么会不知道受控组件?面试就到这里吧。我:😭
版权归许泽川所有
如需转载,请提前询问本人的许可