在Suspense结合使用取数逻辑

react在16.6推出了组件,看了官方文档和一些分析文章,发现以后react的开发方式将会发生重大改变

Suspense功能

声明方式等待任何内容(组件),包括数据,替代react-loadable做code spliting

Suspense 常见API

1.fallback:Suspense里面还有"任务"执行时展示的UI
2.children: 一般是异步组件(配合lazy包裹的异步组件),为什么说一般是,因为官方没提供稳定的api来将取数逻辑跟Suspense配合出延迟效果,但我们可以hack

异步加载组件使用lazy()就一定要Suspense包裹,看了一些分析Suspense源码的文章,了解到Suspense内部是利用componentDidCatch来捕获到lazy主动throw出来的Promise来做条件渲染,渲染fallback内容,待lazy内的Promise状态resolve,完整内容就渲染出来

// lazy内部也是返回了Promise对象
const AsyncCompnentA = lazy(() => import('../componentA'))
export default () => {
  return (
    }>
       
    
 )
}

简易理解中的Suspense源码

class Suspense extends React.Component {
  state = {
     promise: null
  }
  componentDidCatch(e) {
    if(e instanceof Promise) {
        this.setState({
         promise: e,
       }, () => {
        e.then(() => {
           promise: null
        })
      })
    }
  }
  render() {
      return this.state.promise ? this.props.fallback : this.props.children
   }
}

不难理解,通过componentDidCatch捕获的异常改变自身state,然后凭借promise值做条件渲染

而官方没提供取数延迟,貌似暂时只开放给请求库(swr)而非大众调用者,但分析了一波源码,利用throw promise也是可以模拟的

const PromiseThrower = () => {
  const getData = () => {
    const getData = fetch()
    getData.then(data => {
      returnData = data
    })
    if (returnData === cache) {
      throw getData
    }
    return returnData
  }
  return <>{getData()}
}

// useage
export default () => {
  return (
    }>
      
    
  )
}

以往取数组件逻辑

以往loading跟取数(网络请求)完全耦合,三目渲染、样板代码写到吐

const AsyncComponentC = () => {
  const [loading, setLoading] = useState(false)
  useEffect(() => {
      setLoading(true)
      fetch('xxx').then(() => {
        setLoading(false)
     })
  }, [])
 return loading ?  : 
}

未来使用猜想

对于一些短命组件,实时性强且跟应用其它组件少联系的组件,我们大可将数据流范围从应用级(redux之类)收窄至组件本身state,这样让组件更加single,而我们自行封装的取数逻辑(hook)可以在axios,fetch甚至原生xhr上二次封装,在里面loading状态时throw个promise就可以在里有延迟效果了

// usage
const AsyncComponentA = () => {
    const { data } = useFetch('api1')  // 自己封装取数逻辑
    return (
       
{data.whatthe}
) } const AsyncComponentB = () => { const { data } = useFetch('api2') // 自己封装取数逻辑 return (
{data.whatthe}
) } }>

Suspense和改造过的取数hook能带来什么效果

1.loading逻辑和 UI 解耦
2.Suspense可以嵌套使用,声明方式时加载状态顺序可控
3.竞态更加可控

参考文献
1.https://zh-hans.reactjs.org/docs/concurrent-mode-suspense.html#what-if-i-dont-use-relay
2.https://juejin.im/post/5c7d4a785188251b921f4e26#heading-5

你可能感兴趣的:(在Suspense结合使用取数逻辑)