state
React模式
React三种模式:
- legacy模式(平常用的)
- blocking模式(可视为concurrent 的优雅降级版本和过渡版本)
- concurrent模式(未来默认版本,会采用不同 State 更新逻辑,V18)
类组件中的state
setState:更新组件,渲染视图
setState(obj,callback)
参数一:obj为对象时,则为即将合并的 state;obj为函数,则组件的state和 props将作为参数,返回值用于合并新的state。
参数二:函数,函数执行上下文中可获取当前setState更新后的最新state的值,可以作为依赖state变化的副作用函数,可以用于做一些基于DOM的操作。
setState时,React底层如何做的
- setState会产生当前更新的优先级(老版本用expirationTime ,新版本用lane)
- render阶段: React会从fiber Root根部fiber向下调和子节点,调和阶段将对比发生更新的地方,更新对比expirationTime ,找到发生更新的组件,合并state,然后触发render函数,得到新的UI视图层,完成render阶段
- commit阶段,替换真实DOM,完成此次更新流程
- commit阶段,执行setState中callback函数,完成setState全过程
事件系统与批量更新
state更新、UI交互 《==》用户的事件,比如点击事件,表单输入等;React是采用事件合成的形式,每一个事件都是由React事件系统统一调度的。
异步操作里面的批量更新规则会被打破。
React设定了很多不同优先级的更新任务。如果一次更新任务在 flushSync回调函数内部,那么将获得一个较高优先级的更新。
函数组件中的state
useState:
[state , dispatch ] = useState(initData)
监听state变化
把state作为依赖项传入useEffect第二个参数deps;useEffect初始化会默认执行一次.
在useState的dispatchAction处理逻辑中,会浅比较两次state,发现 state相同,不会开启更新调度任务; 所以如果两次state指向了相同的内存空间,就不会发生视图更新了。
解决方式:{...state}浅拷贝对象,重新申请内存空间.
类组件setState和函数组件useState异同
- 原理角度:两者更新视图,底层都调用了scheduleUpdateOnFiber方法,且事件驱动下都有批量更新规则。
- 在不是pureComponent组件模式下, setState不会浅比较两次 state的值;useState中的dispatchAction会默认比较两次state是否相同,再决定更新组件与否。
- setState有回调函数callback监听state,可获取最新state;但函数组件,只能通过useEffect来执行state变化引起的副作用;
- setState在底层处理逻辑上主要是和老state进行合并处理,而 useState更倾向于重新赋值