React Suspense

React Suspense I

import * as React from 'react'
import { Suspense } from 'react'
import { createRoot } from 'react-dom/client'

const resource = (() => {
  let data = null
  let status = 'pending'
  let fetcher = null
  return {
    get() {
      if (status === 'ready') {
        return data
      }
      if (status === 'pending') {
        fetcher = new Promise((resolve, reject) => {
          setTimeout(() => {
            data = 1
            status = 'ready'
            resolve()
          }, 100)
        })
        status = 'fetching'
      }

      throw fetcher
    }
  }
})()

function A() {
  console.log('A1')
  const data = resource.get()
  console.log('A2')
  return <p>{data}</p>
}

function Fallback() {
  console.log('fallback')
  return null
}

function App() {
  console.log('App')
  return <div>
    <Suspense fallback={<Fallback/>}>
      <A/>
    </Suspense>
  </div>
}

const root = createRoot(document.getElementById('root'));
root.render(<App/>)

console:“App” “A1” “fallback” “A1” “A2”

A 开始渲染,但随后 resources.get() 抛出待处理的 Promise,此时激活了Suspense组件,转向了 Suspense 并渲染其后备组件。

React 文档的描述 - “只有支持 Suspense 的数据源才会激活 Suspense 组件”。
请添加图片描述
请添加图片描述

在 Promise resolve后,A重新渲染
请添加图片描述

React Suspense II

import * as React from 'react'
import { Suspense } from 'react'
import { createRoot } from 'react-dom/client'

const resource = (() => {
  let data = null
  let status = 'pending'
  let fetcher = null
  return {
    get() {
      if (status === 'ready') {
        return data
      }
      if (status === 'pending') {
        fetcher = new Promise((resolve, reject) => {
          setTimeout(() => {
            data = 1
            status = 'ready'
            resolve()
          }, 100)
        })
        status = 'fetching'
      }

      throw fetcher
    }
  }
})()

function A() {
  console.log('A1')
  const data = resource.get()
  console.log('A2')
  return <p>{data}</p>
}

function B() {
  console.log('B')
  return null
}

function Fallback() {
  console.log('fallback')
  return null
}

function App() {
  console.log('App')
  return <div>
    <Suspense fallback={<Fallback/>}>
      <A/>
      <B/>
    </Suspense>
  </div>
}

const root = createRoot(document.getElementById('root'));
root.render(<App/>)

console:“App” “A1” “B” “fallback” “A1” “A2” “B”

  • Suspense“检查”所有组件,即每个组件的主体代码都会被执行。
  • 首先渲染 APP组件记录“App”
  • 接下来,在 Suspense 中渲染组件:第一个组件A 记录A1,第二个组件 B记录B
  • React 将显示自定义加载fallback,直到加载完子级所需的所有代码和数据
  • 接下来,在所有加载结束后,Suspense 卸载后备组件并再次渲染子组件记录"A1" “A2” “B”

React Suspense III

import * as React from 'react'
import { Suspense, useMemo } from 'react'
import { createRoot } from 'react-dom'

const resource = (() => {
  let data = null
  let status = 'pending'
  let fetcher = null
  return {
    get() {
      if (status === 'ready') {
        return data
      }
      if (status === 'pending') {
        fetcher = new Promise((resolve, reject) => {
          setTimeout(() => {
            data = 1
            status = 'ready'
            resolve()
          }, 100)
        })
        status = 'fetching'
      }

      throw fetcher
    }
  }
})()


function A() {
  console.log(1)
  const memoed = useMemo(() => {
    console.log(2)
    return 'memo'
  }, [])

  const data = resource.get()
  console.log(3)
  return memoed + data
}

function App() {
  return <Suspense fallback={null}>
    <A/>
  </Suspense>
}

const root = createRoot(document.getElementById('root'));
root.render(<App/>)

console:
“1”
“2”
“1”
“2” // 组件里useMemo函数会再次调用,并再次将 2 记录到控制台
“3”

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值