React18
1.useSelector的作用
它是react-redux库中的一个方法,它的作用是将state映射到组件中。
相对应也有一个useDispatch,他能直接获取dispatch函数,之后在组件中直接使用即可。
2.useSelector的原理
它是react-redux的一个hook,它可以在不使用connect()的情况下将函数组件连接到redux。它的原理是通过selector函数得到需要的数据,并且通过subscribe向store注册回调,在每次state发生变化的时候都会重新调用selector函数对其返回值使用比较函数进行比较,如果两者不同,就会重新渲染当前组件。
useSelector是如何更新页面的呢?
const [,forceRender] = useReducer(s => s+1 ,0)
使用useReducer返回的第二个参数更新页面
3. React的渲染流程
可以将react运行的主干逻辑进行概括:
- 输入:将每次更新(如:新增、删除、修改节点之后)视为一次 更新需求(目的是要更新DOM节点)
- 注册调度任务:react-reconciler收到更新需求后,并不会立即创建fiber树,而是去调度中心scheduler 注册一个一个新任务task,即把更新需求转换成一个task。
- 执行调度任务(输出):调度中心scheduler通过任务调度循环来执行task(task执行过程又回到了react-reconciler包中)。
- fiber构造循环 是 task 的实现环节之一,循环完成之后会构造出最新的 fiber树
- commitRoot 是 task 的实现环节之二,把最新的 fiber树 最终渲染到页面上,task完成
react的渲染主要分为render和commit阶段:
- render阶段将vdom转化为fiber树,commit阶段更新dom、执行effect等副作用逻辑
- commit又分为三个阶段:before mutation(useEffect->宏任务是异步执行)、mutation(页面更新)、layout(useLayoutEffect)
render阶段是可以打断的、是有优先级的,而且render可能执行多次
commit是同步执行的,所以虽然useEffect的调用在页面更新之前,但它的执行却在页面更新之后,因为它是宏任务
4. setState发生了什么?
- 调用enqueueSetState 进入更新入口
- 调用requestUpdateLane 获取本次更新的优先级
- 根据返回的优先级,用于 fiber树的构造。针对 fiber对象或update对象 只要它们的优先级比渲染优先级 低,都将会被忽略
- ⭐接下来进入更新
- 更新分为2种情况,分 同步更新模式 和 并发更新模式
- 如果是同步模式,页面的更新 将在 微任务 种进行异步更新。
- 如果使用到 useTransition、useDeferredValue等将进入 低优先级并发更新模式。这种模式在宏任务中进行异步渲染
5. 什么是合成事件?
React基于浏览器的事件机制自身实现了一套事件机制,这套事件机制我们通常称之为合成事件。它是为了解决不同浏览器的兼容性,因此用户不需要去做兼容开发,而且它还考虑了内存和性能。
事件委托: 例如原生开发中的click事件,如果一个页面中有多个按钮 就生成多个click事件的话,那么其实很不利于事件回收。因此,事件委托就是利用事件冒泡,把页面中的click事件都委托给document,意味着这个页面只有一个click,就很便于管理。
React 16.x及以前的合成事件:
- 事件委托到document
- 部分事件还是会绑定到当前元素
- 存在React事件和原生事件的映射关系,比如onMouseLeave会映射成原生的mouseout事件
- 事件池机制
⭐React17后的合成事件
- 事件委托到root (
<div id="app"></div>) :因为如果大家的事件都委托到document上,可能会导致冲突 - React capture阶段的合成事件提前到原生事件的capture阶段执行
- 移除事件池机制
- 事件有优先级
6. 为什么使用合成事件?
- 为了浏览器兼容
- 多平台适配、ReactNative也能使用
- 实现事件委托,避免大量创建事件监听
7. react18有几种渲染模式
2种:同步模式、并发模式。
默认是同步模式,没有开启并发更新特性。
可使用useTransition、useDeferredValue开启并发更新
8. setState是同步还是异步?
是异步的。
- 同步模式中,更新是微任务异步
- 并发模式中,更新是宏任务异步。宏任务基于 postMessage 实现的。(为什么不用setTimeout,因为时间不准确
9. useEffect副作用队列的顺序?
节点层级越深 越靠前,从最底层节点往上收集effect的回调。
10. Hooks解决了什么问题?
- 状态复用、逻辑复用
- React官方的理念,并不想把hooks和生命周期混为一谈。例如 useEffect调用是在渲染前,执行在渲染后,其实并对应不上某一个生命周期。
11. Redux解决了什么问题?
- 数据状态管理,可以让 数据到视图一一对应
- 可以实现数据回退
- 利用action和dev-tools 方便调试
12. Redux解决了组件通信吗?
redux的模型并不是组件通信,redux的核心原理实际上是action修改store,store变化引起组件重新渲染。vue中的$emit更像组件通信。
13. Context解决了什么问题?可以代替Redux吗?
解决了组件跨层级状态传递。
不可代替redux,context更适合封装复杂组件用,redux更适合管理整个项目数据状态。而且context无法实现数据回退 不好调试。
14. React18 严格模式有什么特点?
- 有些生命周期会执行两次,确保正确的代码,因为fiber架构下,render执行的次数是不确定的
- 一些废弃方法的警告