经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » React » 查看文章
React中Portals与错误边界处理实现
来源:jb51  时间:2021/7/21 20:21:11  对本文有异议

Portals

可以说是 插槽,但 不同于 Vue 中的 slot,它指的是将一个 React 元素渲染到指定的容器 (真实 DOM) 中

比如说,Modal 组件一般默认直接作为 body 的真实结构的子元素渲染出来,那么我们就可以借助 ReactDOM.createPortal(ReactElement, RealDOM container) 创建一个 React 元素,示例代码:

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import Modal from './components/Modal'
  4.  
  5. const PortalModal = ReactDOM.createPortal(<Modal />, document.body)
  6.  
  7. export default function App() {
  8. return <div className="app-container">
  9. <PortalModal />
  10. </div>
  11. }
  12.  

我们可以在浏览器控制台中看到,真实的 Modal 组件其实是作为 body 的直接子元素渲染出来的,但通过 React 开发者工具,我们可以看到 Modal 组件在虚拟 DOM 树的结构中依旧在 App 组件下,类名为 app-container 的 div 中

所以,我们可以得出结论:React 组件虚拟 DOM 树结构与真实 DOM 树结构可以是不一致的

因而需要注意事件冒泡

  • React 中的事件其实是经过包装的
  • 它的事件冒泡是根据虚拟 DOM 树的结构来冒泡的,而不是真实 DOM 树的冒泡机制

错误边界处理

默认情况下,若一个组件在渲染期间 (render) 发生错误,那么就会导致整个组件树全部被卸载
错误边界:就是一个组件,用于捕获 渲染期间 子组件发生的错误,并有能力阻止错误继续向父组件传播

让某个组件捕获错误 (类组件):

使用静态方法 static getDerivedStateFromError,子组件渲染错误时会触发此函数

  • 静态方法,所以不能使用 this
  • 此函数返回值 (对象) 会与 state 混合覆盖状态
  • 触发时间点为:渲染子组件发生错误后,在更新页面之前
  • 只有子组件渲染发生错误,才会触发 (即自身组件发生错误或其兄弟组件、父组件发生错误均不会触发)
  1. import React, {PureComponent} from 'react'
  2.  
  3. export default class ErrorBoundary extends PureComponent {
  4. state = {
  5. isError: false
  6. }
  7. static getDerivedStateFromError(error) {
  8. console.log('Rendering Error: ', error)
  9. return {
  10. isError: true
  11. }
  12. }
  13. render() {
  14. if (this.isError) {
  15. return <span>Something Wrong...</span>
  16. }
  17. return this.props.children
  18. }
  19. }
  20.  

使用 componentDidCatch(error, info) 函数

  • 是个实例方法
  • 运行时机在渲染子组件发生错误后,且页面更新之后 (更改状态会导致组件树卸载完之后又重新构建组件树,比较浪费效率)
  • 通常该函数用于往后台传递并记录错误信息
  1. import React, {PureComponent} from 'react'
  2.  
  3. export default class ErrorBoundary extends PureComponent {
  4. state = {
  5. isError: false
  6. }
  7. componentDidCatch(error, info) {
  8. // info 即为错误的摘要信息
  9. console.log('Rendering Error: ', error)
  10. console.log('Rendering info: ', info)
  11. this.setState({
  12. isError: true
  13. })
  14. }
  15. render() {
  16. if (this.isError) {
  17. return <span>Something Wrong...</span>
  18. }
  19. return this.props.children
  20. }
  21. }

如果没有使用错误边界会怎样?

自 React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载。

经验告诉我们,完全移除比保留错误UI更好。例如,在类似 Messenger 的产品中,把异常的 UI 展示给用户可能会导致用户将信息错发给别人。

增加错误边界能够让你在应用发生异常时提供更好的用户体验。例如,Facebook Messenger 将侧边栏、信息面板、聊天记录以及信息输入框包装在单独的错误边界中。如果其中的某些 UI 组件崩溃,其余部分仍然能够交互。

注意点

某些错误,错误边界组件不会捕获

自身组件的错误

异步的错误 (如 setTimeout 中抛出的错误)

  1. import React, {PureComponent} from 'react'
  2.  
  3. // ErrorBoundary.jsx
  4. export default class ErrorBoundary extends PureComponent {
  5. state = {
  6. isError: false
  7. }
  8. /* 此函数不会运行 */
  9. static getDerivedStateFromError(error) {
  10. console.log('Rendering Error: ', error)
  11. return {
  12. isError: true
  13. }
  14. }
  15. render() {
  16. if (this.isError) {
  17. return <span>Something Wrong...</span>
  18. }
  19. return this.props.children
  20. }
  21. }
  22.  
  23. // Comp.jsx Comp 组件
  24. export default funtion Comp() {
  25. setTimeout(() => {
  26. throw new Error('setTimeout error')
  27. }, 1000)
  28. return <div>Comp</div>
  29. }
  30.  
  31. // App.jsx 使用
  32. export default function App() {
  33. return <>
  34. <ErrorBoundary>
  35. <Comp />
  36. </ErrorBoundary>
  37. </>
  38. }
  39.  

事件中抛出的错误

即:仅处理渲染子组件期间的同步错误

到此这篇关于React中Portals与错误边界处理实现的文章就介绍到这了,更多相关React Portals与错误边界处理内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue! 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号