Skip to content

Framework Comparison

This guide helps you understand the differences between React and Svelte when using Annota.

import {
AnnotaProvider,
AnnotaViewer,
Annotator,
AnnotationPopup,
} from "annota";
import {
useAnnotator,
useAnnotations,
useSelection,
useTool,
} from "annota";
import { useAnnotator } from "annota";
function MyComponent() {
const annotator = useAnnotator();
if (!annotator) return null;
return <div>Annotations: {annotator.state.store.all().length}</div>;
}
import { useAnnotations } from "annota";
function AnnotationList() {
const annotations = useAnnotations();
return (
<ul>
{annotations.map((ann) => (
<li key={ann.id}>{ann.shape.type}</li>
))}
</ul>
);
}
import { useSelection } from "annota";
function SelectionInfo() {
const selection = useSelection();
return <p>Selected: {selection.length}</p>;
}
import { useTool } from "annota";
import { RectangleTool } from "annota";
function ToolController({ viewer }) {
const tool = new RectangleTool();
useTool({
viewer,
handler: tool,
enabled: true,
});
return null;
}
import { AnnotaProvider, AnnotaViewer, Annotator } from "annota";
function App() {
const [viewer, setViewer] = useState(null);
return (
<AnnotaProvider slideId="my-slide">
<AnnotaViewer onViewerReady={setViewer} />
<Annotator viewer={viewer} />
</AnnotaProvider>
);
}
ReactSvelte
{condition && <Component />}{#if condition}<Component />{/if}
{condition ? <A /> : <B />}{#if condition}<A />{:else}<B />{/if}
{!condition && <Component />}{#if !condition}<Component />{/if}
ReactSvelte
{items.map(item => <div key={item.id}>{item.name}</div>)}{#each items as item (item.id)}<div>{item.name}</div>{/each}
Use key prop for keysUse (item.id) for keys
ReactSvelte
const [state, setState] = useState()let state = $state()
const memo = useMemo(() => ..., [deps])const memo = $derived(...)
useEffect(() => ..., [deps])$effect(() => ...)
useCallback(fn, [deps])Function declarations (no deps)
import { useAnnotator } from "annota";
import { useEffect } from "react";
function LoadAnnotations({ slideId }) {
const annotator = useAnnotator();
useEffect(() => {
if (!annotator) return;
fetch(`/api/annotations/${slideId}`)
.then(res => res.json())
.then(anns => annotator.addAnnotations(anns));
}, [annotator, slideId]);
return null;
}
<Annotator
viewer={viewer}
style={(annotation) => ({
fill: annotation.properties?.type === "tumor" ? "#FF0000" : "#00FF00",
fillOpacity: 0.3,
})}
/>
  1. Replace hooks with stores:

    • useAnnotator()getAnnotator()() with $derived
    • useAnnotations()annotations()
    • useSelection()selection()
  2. Update state syntax:

    • useState()$state()
    • useMemo()$derived()
    • useEffect()$effect()
  3. Change JSX to Svelte syntax:

    • classNameclass
    • style={{...}}style="..."
    • onClick={...}onclick={...}
  4. Update imports:

    • from "annota"from "annota/svelte"
  1. Replace stores with hooks:

    • annotations()useAnnotations()
    • selection()useSelection()
    • getAnnotator()()useAnnotator()
  2. Update state syntax:

    • $state()useState()
    • $derived()useMemo()
    • $effect()useEffect()
  3. Change Svelte syntax to JSX:

    • classclassName
    • onclickonClick
    • {#if}{&&} or ternary
  4. Update imports:

    • from "annota/svelte"from "annota"