Export & errors
Render the whole view to a vector SVG (or rasterized PNG), and catch and render view errors with your own UI.
Export the view (SVG/PNG)
exportSvg renders the whole view to a publication-ready vector image, reached
through a ref (or
state.session.view under createViewState):
await ref.current.session.view.exportSvg({ filename: 'volvox.svg' })
It resolves once every visible track has re-rendered through the SVG code path,
then hands the result to the browser’s download flow. format: 'png' rasterizes
the same markup; trackLabels, themeName and fontSize tune the output.
Options:
ExportSvgOptions.
View source — 80 lines
import { useRef, useState } from 'react'
import { ErrorBanner } from '@jbrowse/core/ui'
import { LinearGenomeView } from '@jbrowse/react-linear-genome-view2'
import type { ViewModel } from '@jbrowse/react-linear-genome-view2'
const assembly = {
name: 'volvox',
uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
}
const tracks = [
{
type: 'FeatureTrack',
trackId: 'volvox_gff3',
name: 'Volvox genes',
assemblyNames: ['volvox'],
adapter: {
type: 'Gff3TabixAdapter',
uri: 'https://jbrowse.org/code/jb2/main/test_data/volvox/volvox.sort.gff3.gz',
},
},
]
export default function ExportSvg() {
const ref = useRef<ViewModel>(null)
const [busy, setBusy] = useState(false)
const [error, setError] = useState<unknown>()
// exportSvg is an async action on the view model — it renders every track
// through the SVG code path and hands the result to FileSaver. format 'png'
// rasterizes the same markup. See #action-exportsvg in the docs below.
async function download(format: 'svg' | 'png') {
setBusy(true)
setError(undefined)
try {
await ref.current?.session.view.exportSvg({
filename: `volvox.${format}`,
format,
})
} catch (e) {
setError(e)
} finally {
setBusy(false)
}
}
return (
<div>
<div style={{ marginBottom: 8 }}>
<button
disabled={busy}
style={{ marginRight: 8 }}
onClick={() => {
void download('svg')
}}
>
Export SVG
</button>
<button
disabled={busy}
onClick={() => {
void download('png')
}}
>
Export PNG
</button>
{busy ? ' Rendering…' : null}
</div>
{error ? <ErrorBanner error={error} /> : null}
<LinearGenomeView
ref={ref}
assembly={assembly}
tracks={tracks}
init={{ loc: 'ctgA:1..50,000', tracks: ['volvox_gff3'] }}
/>
</div>
)
}Custom error handling
The embedded view ships no error boundary, so catching errors is the host app’s job. There are two kinds:
- construction —
createViewStatevalidates the config and can throw a (verbose)@jbrowse/mobx-state-treeerror. Wrap the call in try/catch. - runtime — observable at
viewState.session.view.error. Anobservercan render your own UI when it becomes truthy.
For both, ErrorBanner from @jbrowse/core/ui is an error display (not a
React error boundary): it formats JBrowse errors with a stack-trace button and,
for validation failures, the offending config snapshot. ErrorMessage is the
plain-text sibling.
This demo configures a BadTrack track type that fails validation, so the
banner has something real to render.
View source — 43 lines
import { useState } from 'react'
import { ErrorBanner } from '@jbrowse/core/ui'
import {
JBrowseLinearGenomeView,
createViewState,
} from '@jbrowse/react-linear-genome-view2'
import type { ViewModel } from '@jbrowse/react-linear-genome-view2'
export default function WithErrorHandler() {
// createViewState builds the whole model synchronously, so it either hands
// back an engine or throws — there is no third, still-loading state
const [result] = useState<{ viewState: ViewModel } | { error: unknown }>(
() => {
try {
return {
viewState: createViewState({
assembly: {
name: 'volvox',
uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit',
},
tracks: [
{
type: 'BadTrack',
notProperTrack: 'error',
shouldHaveTrackIdAndStuff: 'test',
},
],
location: 'ctgA:1105..1221',
}),
}
} catch (error) {
return { error }
}
},
)
return 'error' in result ? (
<ErrorBanner error={result.error} />
) : (
<JBrowseLinearGenomeView viewState={result.viewState} />
)
}