JBrowse 2 · React App examples

Loading configuration

Import or fetch a config.json, or add tracks and views later.

Import a config.json

URIs in a config.json are relative to where it was served, so addRelativeUris resolves them against that URL. The file’s shape is JBrowseRootConfig.

View source — 13 lines
import { addRelativeUris } from '@jbrowse/core/util/addRelativeUris'
import { JBrowseApp, useCreateViewState } from '@jbrowse/react-app2'

import config from '../volvox-config.json' with { type: 'json' }

const configUrl =
  'https://jbrowse.org/code/jb2/main/test_data/volvox/config.json'
addRelativeUris(config, new URL(configUrl))

export default function WithImportConfigJson() {
  const state = useCreateViewState({ config })
  return state ? <JBrowseApp viewState={state} /> : null
}

Fetch a config.json

Unlike JBrowse Web, the embedded app does not load a config’s plugins: hand them to loadPlugins, whose baseUri resolves a relative plugin URL against the config rather than your page.

View source — 28 lines
import { addRelativeUris } from '@jbrowse/core/util/addRelativeUris'
import {
  JBrowseApp,
  createViewStateAsync,
  loadPlugins,
  useCreateViewState,
} from '@jbrowse/react-app2'

const configUrl =
  'https://jbrowse.org/code/jb2/main/test_data/volvox/config.json'

async function build() {
  const response = await fetch(configUrl)
  if (!response.ok) {
    throw new Error(`HTTP ${response.status} fetching config ${configUrl}`)
  }
  const config = await response.json()
  addRelativeUris(config, new URL(configUrl))
  const plugins = await loadPlugins(config.plugins ?? [], {
    baseUri: configUrl,
  })
  return createViewStateAsync({ config, plugins })
}

export default function WithFetchConfigJson() {
  const state = useCreateViewState(build)
  return state ? <JBrowseApp viewState={state} /> : null
}

Add tracks programmatically

View source — 58 lines
import { useRef, useState } from 'react'

import { JBrowse } from '@jbrowse/react-app2'

import type { ViewModel } from '@jbrowse/react-app2'

const base = 'https://jbrowse.org/code/jb2/main/test_data/volvox'

const assemblies = [
  { name: 'volvox', uri: 'https://jbrowse.org/genomes/volvox/volvox.2bit' },
]

const genesTrackConf = {
  trackId: 'volvox_genes',
  name: 'Volvox genes',
  uri: `${base}/volvox.sort.gff3.gz`,
  assemblyNames: ['volvox'],
}

export default function AddTracksProgrammatically() {
  const ref = useRef<ViewModel>(null)
  const [added, setAdded] = useState(false)

  async function addTrack() {
    const state = ref.current
    if (state) {
      state.jbrowse.addTrackConf(genesTrackConf)
      await state.session.views[0]?.launchTrack('volvox_genes')
      setAdded(true)
    }
  }

  return (
    <div>
      <button
        disabled={added}
        onClick={() => {
          void addTrack()
        }}
      >
        {added ? 'Genes track added' : 'Add genes track'}
      </button>
      <JBrowse
        ref={ref}
        assemblies={assemblies}
        tracks={[]}
        sessionName="Programmatic tracks"
        views={[
          {
            type: 'LinearGenomeView',
            assembly: 'volvox',
            loc: 'ctgA:1..50000',
          },
        ]}
      />
    </div>
  )
}

Launch a view imperatively

session.launchView takes any view type and the same settings a views entry does, and resolves to the new view. Each click opens another view below the last. Automating JBrowse describes the view fields.

View source — 51 lines
import { useRef } from 'react'

import { JBrowse } from '@jbrowse/react-app2'

import type { ViewModel } from '@jbrowse/react-app2'

const assemblies = [
  {
    name: 'GRCh38',
    aliases: ['hg38'],
    uri: 'https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz',
    refNameAliases: {
      uri: 'https://jbrowse.org/genomes/GRCh38/hg38_aliases.txt',
    },
    geneticCodes: { chrM: 2 },
  },
]

const tracks = [
  {
    trackId: 'hg38.100way.phyloP100way',
    name: 'hg38.100way.phyloP100way',
    uri: 'https://hgdownload.soe.ucsc.edu/goldenpath/hg38/phyloP100way/hg38.phyloP100way.bw',
    category: ['Conservation'],
    assemblyNames: ['hg38'],
  },
]

export default function WithLaunchLinearGenomeView() {
  const ref = useRef<ViewModel>(null)

  function openView() {
    const session = ref.current?.session
    session
      ?.launchView('LinearGenomeView', {
        assembly: 'hg38',
        loc: 'chr10:1-100000',
        tracks: ['hg38.100way.phyloP100way'],
      })
      .catch((e: unknown) => {
        session.notifyError(`${e}`, e)
      })
  }

  return (
    <div>
      <button onClick={openView}>Open a linear genome view</button>
      <JBrowse ref={ref} assemblies={assemblies} tracks={tracks} />
    </div>
  )
}