UNPKG

@tanstack/solid-router

Version:

Modern and scalable routing for Solid applications

79 lines 3.08 kB
import * as Solid from 'solid-js'; import { Dynamic } from '@solidjs/web'; import { renderInNonRouteComponentContext } from './nonRouteComponentContext'; export function CatchBoundary(props) { const [retryKey, setRetryKey] = Solid.createSignal({}); let resetBoundary; let initialized = false; let previousKey; Solid.onCleanup(() => { resetBoundary = undefined; }); Solid.createEffect(props.getResetKey, (key) => { if (!initialized) { initialized = true; previousKey = key; return; } // The effect re-runs on every recompute of the key function, not only // on value changes — gate on the value so an unchanged key can't // recreate the retried subtree while it settles. if (key === previousKey) { return; } previousKey = key; const reset = resetBoundary; if (reset) { queueMicrotask(() => { if (resetBoundary !== reset) { return; } setRetryKey({}); reset(); Solid.flush(); }); } }); return (<Solid.Errored fallback={(error, reset) => { const resolvedError = Solid.untrack(() => error()); props.onCatch?.(resolvedError); resetBoundary = reset; return process.env.NODE_ENV !== 'production' ? (renderInNonRouteComponentContext(() => (<Dynamic component={props.errorComponent ?? ErrorComponent} error={resolvedError} reset={reset}/>), 'errorComponent')) : (<Dynamic component={props.errorComponent ?? ErrorComponent} error={resolvedError} reset={reset}/>); }}> <Solid.Show when={retryKey()} keyed> {(_retryKey) => props.render?.() ?? props.children} </Solid.Show> </Solid.Errored>); } export function ErrorComponent({ error }) { const [show, setShow] = Solid.createSignal(process.env.NODE_ENV !== 'production'); return (<div style={{ padding: '.5rem', 'max-width': '100%' }}> <div style={{ display: 'flex', 'align-items': 'center', gap: '.5rem' }}> <strong style={{ 'font-size': '1rem' }}>Something went wrong!</strong> <button style={{ appearance: 'none', 'font-size': '.6em', border: '1px solid currentColor', padding: '.1rem .2rem', 'font-weight': 'bold', 'border-radius': '.25rem', }} onClick={() => setShow((d) => !d)}> {show() ? 'Hide Error' : 'Show Error'} </button> </div> <div style={{ height: '.25rem' }}/> {show() ? (<div> <pre style={{ 'font-size': '.7em', border: '1px solid red', 'border-radius': '.25rem', padding: '.3rem', color: 'red', overflow: 'auto', }}> {error.message ? <code>{error.message}</code> : null} </pre> </div>) : null} </div>); } //# sourceMappingURL=CatchBoundary.jsx.map