Observe state with onChange
onChange fires on every MST patch — persist the session, drive undo/redo, or sync external UI.
Pass an onChange callback to <JBrowse> (alongside the assemblies/tracks/
views from the basic example) to be notified on every
MST patch. It receives the forward patch and
its inverse, so you can persist the session, build an undo/redo stack, or sync
external UI:
<JBrowse
assemblies={assemblies}
tracks={tracks}
views={views}
onChange={(patch, reversePatch) => {
// patch: { op, path, value } — the change that was just applied
// reversePatch: the patch that would undo it
}}
/>
A common use is autosaving the session to localStorage so a reload restores
where the user left off. That needs a full snapshot rather than just the patch,
and restoring a saved session on mount needs a config.defaultSession you
control directly — both call for the unmanaged createViewState +
<JBrowseApp> flow instead of the managed component:
// @jbrowse/mobx-state-tree is JBrowse's bundled MST fork
import { getSnapshot } from '@jbrowse/mobx-state-tree'
const saved = localStorage.getItem('jbrowse-session')
const state = createViewState({
config: {
...config,
defaultSession: saved ? JSON.parse(saved) : config.defaultSession,
},
// runs after construction, so referencing `state` here is safe
onChange: () => {
localStorage.setItem(
'jbrowse-session',
JSON.stringify(getSnapshot(state.session)),
)
},
})
The patch path strings mirror the session state tree. The
BaseSessionModel and
per-view model docs (e.g.
LinearGenomeView) show
which properties live where, so you can tell which patches matter for your use
case.
Live demo
View source
import { useState } from 'react'
import { JBrowse } from '@jbrowse/react-app2'
import { volvoxConfig } from '../volvoxConfig.ts'
// onChange fires on every MST patch. Use it to persist the session (e.g. to
// localStorage or a backend), drive an undo/redo stack, or sync external UI.
export default function WithOnChange() {
const [log, setLog] = useState<string[]>([])
return (
<div>
<div
style={{
padding: 8,
fontFamily: 'monospace',
fontSize: 12,
background: '#8881',
}}
>
<div>Recent session patches (pan/zoom, or show/hide a track):</div>
<pre style={{ margin: 0 }}>
{log.join('\n') || '(interact with the view to see patches)'}
</pre>
</div>
<JBrowse
assemblies={volvoxConfig.assemblies}
tracks={volvoxConfig.tracks}
views={[
{
type: 'LinearGenomeView',
init: {
assembly: 'volvox',
loc: 'ctgA:1..50000',
tracks: ['volvox_cram'],
},
},
]}
onChange={patch => {
setLog(prev => [`${patch.op} ${patch.path}`, ...prev].slice(0, 8))
}}
/>
</div>
)
}