Skip to content

React Integration

Problem

Implement react integration in a production-friendly way with @vielzeug/workit while keeping setup and cleanup explicit.

Runnable Example

The snippet below is copy-paste runnable in a TypeScript project with @vielzeug/workit installed.

Off-load processing from React components without blocking renders:

tsx
import { useEffect, useState } from 'react';
import { createWorker } from '@vielzeug/workit';

type SortInput = { data: number[] };
type SortOutput = { sorted: number[] };

// Create once outside the component — reused across renders
const sortWorker = createWorker<SortInput, SortOutput>(({ data }) => ({ sorted: [...data].sort((a, b) => a - b) }));

export function SortedList({ data }: { data: number[] }) {
  const [sorted, setSorted] = useState<number[]>([]);
  const [pending, setPending] = useState(false);

  useEffect(() => {
    let cancelled = false;
    setPending(true);
    sortWorker.run({ data }).then(({ sorted }) => {
      if (!cancelled) setSorted(sorted);
      setPending(false);
    });
    return () => {
      cancelled = true;
    };
  }, [data]);

  if (pending) return <p>Sorting…</p>;
  return (
    <ul>
      {sorted.map((n) => (
        <li key={n}>{n}</li>
      ))}
    </ul>
  );
}

Expected Output

  • The example runs without type errors in a standard TypeScript setup.
  • The main flow produces the behavior described in the recipe title.

Common Pitfalls

  • Forgetting cleanup/dispose calls can leak listeners or stale state.
  • Skipping explicit typing can hide integration issues until runtime.
  • Not handling error branches makes examples harder to adapt safely.