@tanstack/solid-router
Version:
Modern and scalable routing for Solid applications
79 lines • 3.08 kB
JSX
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