React
生命周期
参考 https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
>= 16.4
为什么在 16.4 版本之后对生命周期进行了大调整?比如废弃了 componentWillMount/componentWillReceiveProps/componentWillUpdate
父子组件生命周期的执行顺序
挂载时,子组件的挂载钩子先被触发;卸载时,子组件的卸载钩子后被触发
babel 插件
@babel/babel-preset-react-app
(<17)react/jsx-runtime
老版本的 React 中,为什么写 jsx 的文件要默认引入 React?
组件分类
- 类组件
- 函数组件
对于类组件来说,底层只需要实例化一次,实例中保存了组件的 state 等状态。对于每一次更新只需要调用 render 方法以及对应的生命周期就可以了。但是在函数组件中,每一次更新都是一次新的函数执行,一次函数组件的更新,里面的变量会重新声明
React 高阶组件是什么,和普通组件有什么区别,适用什么场景
高阶组件(HOC)就是一个函数, 且该函数接受一个组件作为参数, 并返回一个新的组件
优点
- 逻辑复用、不影响被包裹组件的内部逻辑
缺点
- 组件多层嵌套, 增加复杂度
- hoc 传递给被包裹组件的 props 容易和被包裹后的组件重名,进而被覆盖,而且不清楚 props 来源与哪个高阶组件
- ref 隔断问题,React.forwardRef 来解决【WIP】
参考 https://juejin.cn/post/6844903782355042312
react18
一文解读 React 17 与 React 18 的更新变化
三种模式
- legacy
- blocking
- concurrent
https://17.reactjs.org/docs/concurrent-mode-adoption.html#feature-comparison
新增特性
- 自动批量更新
- 订阅外部数据源
- transition
- Offscreen
react18 自动批量更新是如何实现的?
根据优先级 lane,第一个 setState 发起调度更新,后续同等优先级的会跳过调度更新
参考 https://github.com/facebook/react/issues/11527
异常处理
React 中可以定义 ErrorBounding 组件来帮助我们捕获异常(componentDidCatch 或 getDerivedStateFromError),实际上就是子组件在 reconciler 期间,利用 try catch 来捕获报错的组件,即如果遇到错误,则会就被 catch 到,然后从该报错的组件往上找错误边界,只要父组件是类组件,且有实例属性 componentDidCatch 或静态属性 getDerivedStateFromError,那么就判定为错误边界,同时在上述两个方法中可以修改 state,从而渲染出备用的 ui,而不至于直接让页面白屏
不过有局限性,以下是无法处理的情况:
- 事件处理函数,如 onClick,onMouseEnter
- 异步代码,如 requestAnimationFrame,setTimeout,promise
- 服务端渲染
- ErrorBoundary 组件本身的错误
创建一个基础的 ErrorBounding 组件
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
logErrorToMyService(error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
参考
优化手段
减少组件重渲染
- memo/shouldComponentUpdate
- useMemo/useCallback
- 批量更新
ReactDOM.unstable_batchedUpdates
(react18 之前适用,react18 已有自动批量更新)
减少节点
- 惰性渲染(懒加载)
- 虚拟列表
降低渲染计算量
- 缓存结果或对象 useMemo/useCallback
- webWorker
精细化渲染
- 参考 mobx 和 vue
- 不滥用 Context