React面试
React 面试
React 性能优化
PureComponent, shouldComponentUpdate, memo, useMemo, useCallback 进行优化
react-redux, useSelector, 尽量不要在 selector 里面组装结果,需要组装可以传入 equal 函数优化,或者使用 reselect 库
useState 惰性初始化
对于经常需要重新渲染的组件,我们可以提取出子组件并用 memo 优化
useRef 使用场景
访问 dom 或 class 组件
通过 ref 访问最新的 state/props,而不需要将 state/props 作为 useEffect,useMemo 等的依赖
用来存储初始化时的 props,不再关注后续 props 变化
在 setTimeout 里面使用,避免闭包陷阱
组件封装思考
提供哪些 props,重要:考虑哪些 props 只做初始化【defaultValue】,后续变化无效。 受控组件,非受控组件
函数组件考虑 ref 转发,通过 ref 向外界传递哪些值或函数
优先封装成函数,或者 hook,与 UI 解耦,更易复用
虚拟 DOM 是什么?
真实 DOM 的抽象,js 对象(element tree,fiber tree)
为什么需要虚拟 DOM?/ 讲讲虚拟 DOM
React 理念是数据驱动视图,虚拟 DOM 是视图(真实 DOM)的抽象,我们只需要修改数据生成新的虚拟 DOM, 再通过 dom diff,便能高效的更新视图
如果没有虚拟 DOM,某个组件更新,组件代表的真实 DOM 及子节点可能都需要重新生成
DOM diff 算法
不同类型的元素,我们认为它的子节点也是不同的,直接替换这个节点
相同类型的 dom,我们根据需要更新 dom 属性
相同类型的 react 组件,我们根据需要更新 props,执行 render 方法,在 children 上重复这样的操作
对于列表,如果 key 不同,认为不是相同节点,key 相同,再比较其他属性或 props 【列表 diff 有比较复杂的算法】
React 和 Vue
相同: 1. 组件化 2.VDom dom-diff 3.数据驱动视图,都是改变数据来改变视图
不同: 1. jsx vs 模版语法(vue-jsx 语法没用过) 2. 数据驱动视图的原理不太一样,vue 依赖收集和 dom-diff,react 完全依靠 dom-diff,当然 react 提供了一些优化手段(memo 等) 3. 使用体验,react 由于 jsx 语法,和写原生 js 差不多,能利用函数式编程的优势:函数就是组件,render-props,高级组件等都是函数作为一等公民的优势。
render 和 commit 阶段
渲染阶段:可以中断重新执行,所以其中的生命周期可能多次执行。从根节点开始遍历 Fiber Node,并且构建 WorkInProgress Tree,通过 Diff 算法计算所有更新工作,生成 EffectList
提交阶段:根据 EffectList 更新 DOM
tips
React 内部使用 createTextNode 创建文本节点,减少了 xss。对于 a 标签 href 的 xss 目前仅仅给出警告。
每次重新渲染都会重新创建 Element,但是 FiberNode 不会,FiberNode 只会使用对应的 Element 中的数据来更新自己必要的属性
React.lazy 语法,可以实现组件的懒加载,通常基于路由懒加载。不能用于服务端渲染(服务端请用 Loadable),需要在外层包裹 Suspense,加载失败会报错。
React.lazy 目前只支持默认导出
Context 的值改变,所有用到 context 的值的地方都会重新渲染(不受 React.Memo 和 shouldComponentUpdate 的约束)。
Context 不能代替 redux,context 对象引用改变,所有用到 context 的组件会重新渲染;context 对象引用不改变(仅仅内部属性改变),组件不会重新渲染。
static getDerivedStateFromError: 处于 render 阶段,可能执行多次,不适合再此处发送错误日志等副作用操作!!!
componentDidCatch:处于 commit 阶段,适合做副作用操作,如发送错误日志!!!
renderProps:接受一个函数,返回 react element,可以将内部 state 通过函数参数共享出去。【向外部共享内部 state】
惰性初始 state, 如果初始化 state 花费过高,可以传函数给 useState, 函数只在初始化渲染调用。
render 和 commit 阶段生命周期
render 阶段会执行以下的生命周期钩子:
[UNSAFE_]componentWillMount(弃用)
[UNSAFE_]componentWillReceiveProps(弃用)
static getDerivedStateFromProps
static getDerivedStateFromError
shouldComponentUpdate
[UNSAFE_]componentWillUpdate(弃用)
render
Commit 阶段会执行如下生命周期方法:
getSnapshotBeforeUpdate
componentDidMount
componentDidUpdate
componentWillUnmount
componentDidCatch
最后更新于
这有帮助吗?