import React , { createContext , useRef , useContext , Suspense , useEffect , ReactElement } from 'react' ; import { useRenderedEffect } from '../lifecycles' ; const createPartialContextValue = ( ) => { let chain = Promise . resolve ( ) ; const register = ( ) => { let resolver ; const currentPromise = chain ; const nextPromise = new Promise < undefined > ( resolve => { resolver = ( ) => resolve ( undefined ) ; } ) ; chain = chain . then ( ( ) => nextPromise ) ; return [ currentPromise , resolver ] ; } ; return { register , } ; } ; const PartialContext = createContext ( createPartialContextValue ( ) ) ; export const PartialProvider = ( { children } ) => ( < PartialContext . Provider value = { createPartialContextValue ( ) } > { children } < /PartialContext.Provider>); const DelayComp = ( { children , promise , resolver } ) => { if ( promise . current !== null && resolver . current ) { throw promise . current ; } useRenderedEffect ( ( ) => { if ( resolver . current ) { resolver . current ( ) ; resolver . current = null ; } } , [ promise . current ] ) ; return children ; } ; export const Partial = ( { children , fallback , } ) => { const pending = useRef ( true ) ; const { register } = useContext ( PartialContext ) ; const resolverRef = useRef ( null ) ; const promiseRef = useRef ( null ) ; if ( pending . current ) { const [ promise , resolver ] = register ( ) ; resolverRef . current = resolver ; promiseRef . current = promise ; } useEffect ( ( ) => { pending . current = false ; promiseRef . current = null ; } , [ ] ) ; return ( < Suspense fallback = { fallback || null } > < DelayComp promise = { promiseRef } resolver = { resolverRef } > { children } < /DelayComp> < /Suspense>); } ;