Skip to main content
Module

x/nano_jsx/components/suspense.ts

🎯 SSR first, lightweight 1kB JSX library.
Go to Latest
File
import { Component } from '../component.ts'import { isSSR, strToHash } from '../core.ts'
interface Props { fallback: any cache?: boolean [key: string]: any}
export class Suspense extends Component<Props> { ready = false
constructor(props: Props) { super(props)
// get props promises in ...rest const { children, fallback, cache = false, ...rest } = this.props
// stringify ...rest const str = JSON.stringify(rest, function (_key, val) { if (typeof val === 'function') return `${val}` // implicitly `toString` it return val })
// create unique id based on ...rest this.id = strToHash(JSON.stringify(str)) }
async didMount() { // get props promises in ...rest const { children, fallback, cache = false, ...rest } = this.props
// set initial state to [] if (cache) this.initState = {}
// check if we already cached the results in this.state if (this.loadFromCache(cache)) return
// resolve the promises const promises = Object.values(rest).map(p => p()) const resolved = await Promise.all(promises)
// prepare data const data = this.prepareData(rest, resolved, cache)
// add data to children this.addDataToChildren(data)
// update the component this.ready = true this.update() }
ssr() { // get props promises in ...rest const { children, fallback, cache = false, ...rest } = this.props
// execute the functions const functions = Object.values(rest).map(p => p())
// prepare data const data = this.prepareData(rest, functions, false)
// add data to children this.addDataToChildren(data) }
loadFromCache(cache: boolean) { const hasCachedProps = this.state && cache && Object.keys(this.state).length > 0
if (hasCachedProps) { this.addDataToChildren(this.state) this.ready = true }
return hasCachedProps }
prepareData(rest: any, fnc: Function[], cache: boolean) { const data = Object.keys(rest).reduce((obj, item, index) => { if (cache) this.state = { ...this.state, [item]: fnc[index] } return { ...obj, [item]: fnc[index] } }, {}) return data }
addDataToChildren(data: any) { // add data as props to children this.props.children.forEach((child: any) => { if (child.props) child.props = { ...child.props, ...data } }) }
render() { if (!isSSR()) { const { cache = false } = this.props this.loadFromCache(cache) return !this.ready ? this.props.fallback : this.props.children } else { this.ssr() return this.props.children } }}