UNPKG

react-universal-component

Version:

A higher order component for loading components with promises

135 lines (117 loc) 3.29 kB
// @flow import * as React from 'react' import requireById from './requireById' import type { Id, Key, Props, LoadingComponent, ErrorComponent, OnLoad, Mod, StrFun } from './flowTypes' export const isTest = process.env.NODE_ENV === 'test' export const isServer = !( typeof window !== 'undefined' && window.document && window.document.createElement ) export const isWebpack = () => typeof __webpack_require__ !== 'undefined' export const babelInterop = (mod: ?Mod) => mod && typeof mod === 'object' && mod.__esModule ? mod.default : mod export const DefaultLoading: LoadingComponent = () => <div>Loading...</div> export const DefaultError: ErrorComponent = ({ error }) => ( <div>Error: {error && error.message}</div> ) export const tryRequire = (id: Id): ?any => { try { return requireById(id) } catch (err) { // warn if there was an error while requiring the chunk during development // this can sometimes lead the server to render the loading component. if (process.env.NODE_ENV === 'development') { console.warn( `chunk not available for synchronous require yet: ${id}: ${ err.message }`, err.stack ) } } return null } export const resolveExport = ( mod: ?Mod, key: ?Key, onLoad: ?OnLoad, chunkName: ?StrFun, props: Object, modCache: Object, isSync?: boolean = false ) => { const exp = findExport(mod, key) if (onLoad && mod) { const isServer = typeof window === 'undefined' const info = { isServer, isSync } onLoad(mod, info, props) } if (chunkName && exp) cacheExport(exp, chunkName, props, modCache) return exp } export const findExport = (mod: ?Mod, key?: Key): ?any => { if (typeof key === 'function') { return key(mod) } else if (key === null) { return mod } return mod && typeof mod === 'object' && key ? mod[key] : babelInterop(mod) } export const createElement = (Component: any, props: {}) => React.isValidElement(Component) ? ( React.cloneElement(Component, props) ) : ( <Component {...props} /> ) export const createDefaultRender = ( Loading: LoadingComponent, Err: ErrorComponent ) => (props: Props, mod: ?any, isLoading: ?boolean, error: ?Error) => { if (isLoading) { return createElement(Loading, props) } else if (error) { return createElement(Err, { ...props, error }) } else if (mod) { // primary usage (for async import loading + errors): return createElement(mod, props) } return createElement(Loading, props) } export const callForString = (strFun: StrFun, props: Object) => typeof strFun === 'function' ? strFun(props) : strFun export const loadFromCache = ( chunkName: StrFun, props: Object, modCache: Object ) => !isServer && modCache[callForString(chunkName, props)] export const cacheExport = ( exp: any, chunkName: StrFun, props: Object, modCache: Object ) => (modCache[callForString(chunkName, props)] = exp) export const loadFromPromiseCache = ( chunkName: StrFun, props: Object, promisecache: Object ) => promisecache[callForString(chunkName, props)] export const cacheProm = ( pr: Promise<*>, chunkName: StrFun, props: Object, promisecache: Object ) => (promisecache[callForString(chunkName, props)] = pr)