UNPKG

@shopify/react-async

Version:

Tools for creating powerful, asynchronously-loaded React components

94 lines (89 loc) 2.49 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var reactEffect = require('@shopify/react-effect'); var reactHooks = require('@shopify/react-hooks'); var assets = require('./context/assets.js'); function usePreload(...args) { const [preloadable, options = {}] = args; return preloadable.usePreload(options); } function usePrefetch(...args) { const [prefetchable, options = {}] = args; return prefetchable.usePrefetch(options); } function useKeepFresh(...args) { const [keepFreshable, options = {}] = args; return keepFreshable.useKeepFresh(options); } function useAsync(resolver, { assets, scripts = assets, styles = assets, immediate = true } = {}) { const [value, setValue] = React.useState(() => immediate || typeof window !== 'undefined' ? resolver.resolved : null); const mounted = reactHooks.useMountedRef(); const load = React.useCallback(async () => { if (value != null) { return value; } try { const resolved = await resolver.resolve(); if (mounted.current) { // It's important to use the function form of setValue here. // Resolved is going to be a function in most cases, since it's // a React component. If you do not set it using the function form, // React treats the component as the function that returns state, // so it sets state with the result of manually calling the component // (so, usually JSX). setValue(() => resolved); } return resolved; } catch (error) { if (mounted.current) { setValue(error); } return error; } }, [mounted, resolver, value]); const { id } = resolver; useAsyncAsset(id, { scripts, styles }); return value instanceof Error ? { id, resolved: null, error: value, loading: false, load } : { id, resolved: value, error: null, loading: value == null, load }; } function useAsyncAsset(id, { scripts, styles } = {}) { const async = React.useContext(assets.AsyncAssetContext); reactEffect.useServerEffect(() => { if (async && id) { async.markAsUsed(id, { scripts, styles }); } }, async === null || async === void 0 ? void 0 : async.effect); } exports.useAsync = useAsync; exports.useAsyncAsset = useAsyncAsset; exports.useKeepFresh = useKeepFresh; exports.usePrefetch = usePrefetch; exports.usePreload = usePreload;