Start / Cheat Sheets

Cheat Sheet

React für Atlassian Forge — Cheat Sheet

Stand: · React-Schulung für Atlassian Forge

ReactTypeScriptAtlassian Forge

Der Spickzettel zur React-Schulung für Atlassian Forge — von modernem JavaScript bis zum Resolver in der Forge-Sandbox. Die Forge-Plattform ändert sich; für Manifest-Schlüssel und CLI-Flags bleibt die Atlassian-Doku maßgeblich.

TypeScript: interface oder type?

Aspektinterfacetype
Erweiternextends& (Intersection)
Union-Typesneinja
Deklarations-Mergejanein
Typischer EinsatzObjektformenUnions, Primitive

Faustregel: Objektformen als interface, alles Übrige als type.

interface User { id: number; name: string; role?: Role }
type ID = string | number

function first<T>(items: T[]): T { return items[0] }
first(["a", "b"])          // T = string (hergeleitet)

In React typisiert man Props und Events explizit:

interface Props { title: string; count?: number }
function Badge({ title, count = 0 }: Props) { … }

const [user, setUser] = useState<User | null>(null)
type Ev = React.ChangeEvent<HTMLInputElement>

Modul: TypeScript für React

React-Grundmuster

// Props sind read-only, children ist eine normale Prop
function Card({ title, children }) {
  return <section><h2>{title}</h2>{children}</section>;
}

// State: Paar aus Wert und Setter
const [count, setCount] = useState(0);

// Liste: stabile ID als key, nie der Array-Index
{items.map((item) => <li key={item.id}>{item.text}</li>)}

// Kontrolliertes Feld: value und onChange gehören zusammen
<input value={name} onChange={(e) => setName(e.target.value)} />

Drei Muster für bedingtes Rendern — if für den frühen Ausstieg, && für „zeige nur wenn”, der Ternär für „entweder/oder”:

if (loading) return <p>Lädt…</p>;
{user && <span>Hi {user.name}</span>}
{user ? <Logout /> : <Login />}

Modul: React-Grundlagen

Wo gehört der State hin?

SituationPassende Ebene
Nur eine Komponente nutzt ihnLokaler useState
Zwei Geschwister teilen ihnIn den Vorfahren heben
Ganzer Teilbaum braucht ihnContext API
Serverdaten, Caching, SyncData-Library (z. B. React Query)

Erst lokal, dann heben, dann Context — in dieser Reihenfolge.

PatternWofür
Lifting State UpGeschwister synchron halten
Controlled ComponentFormularwerte in React kontrollieren
Composition (children)Flexible, wiederverwendbare Layouts
Custom HookLogik kapseln und wiederverwenden
function useToggle(start = false) {
  const [on, setOn] = useState(start);
  return [on, () => setOn((v) => !v)];
}

Ein Custom Hook beginnt mit use — sonst greifen die Hook-Regeln nicht. Er kapselt Logik, kein JSX.

Modul: State Management in React

Projektstruktur

src/
  features/
    todos/
      TodoListe.jsx
      useTodos.js
      todos.api.js
  components/   # geteilte UI
  lib/          # Hilfsfunktionen

Bei kleinen Projekten reicht typ-basiert; feature-basiert lohnt ab mittlerer Größe. Struktur nicht dogmatisch erzwingen, sondern mitwachsen lassen.

Modul: React-Projektstruktur und Best Practices

Atlassian Forge

manifest.yml ist die zentrale Wahrheit über Module, Rechte und Ressourcen:

modules:
  jira:issuePanel:
    - key: hallo-panel
      resource: main
      title: Hallo Forge
resources:
  - key: main
    path: src/frontend/index.jsx
npm install -g @forge/cli
forge login          # E-Mail + API-Token, nicht das Passwort
forge whoami
forge lint
forge deploy -e development
forge install --site meine.atlassian.net
forge tunnel         # lokaler Code, Hot Reload

Im UI Kit gibt es keine HTML-Tags — nur Komponenten aus @forge/react:

import ForgeReconciler, { Button, useState } from "@forge/react";
const App = () => {
  const [n, setN] = useState(0);
  return <Button onClick={() => setN(n + 1)}>Klicks: {n}</Button>;
};
ForgeReconciler.render(<App />);
import Resolver from "@forge/resolver";
import { storage } from "@forge/api";
const resolver = new Resolver();
resolver.define("save", ({ payload }) => storage.set("note", payload.text));
export const handler = resolver.getDefinitions();

Der invoke-Name im Frontend muss exakt dem resolver.define-Namen entsprechen.

Modul: React im Atlassian-Forge-Umfeld

Typische Fallen

JavaScript / TypeScript

  • == erzwingt Typumwandlung — im Zweifel immer ===.
  • Arrow Functions haben kein eigenes this — als Objektmethode unbrauchbar.
  • Vergessenes await liefert ein Promise statt des Werts.
  • any breitet sich aus und hebelt die Prüfung aus; @ts-ignore ist keine Dauerlösung.
  • tsc erzeugt trotz Typfehler Output, solange noEmitOnError fehlt.
  • Dateien mit JSX brauchen .tsx, nicht .ts.

React

  • Der Array-Index als key bricht bei Umsortieren oder Einfügen.
  • {count && …} rendert bei 0 die Zahl 0 — besser count > 0 prüfen.
  • onClick={handleClick()} ruft sofort auf; die Klammern gehören weg.
  • State direkt mutieren (count++) löst kein Re-Render aus. Objekte und Arrays neu erzeugen — und daran denken, dass Spread nur flach kopiert.
  • State-Updates sind asynchron. Mehrere Updates im selben Event brauchen die Updater-Form setX(v => …).
  • Hooks nur auf oberster Ebene — nie in Schleifen oder Bedingungen.
  • Fehlende Dependencies im Effekt führen zu veralteten Werten; fehlendes Cleanup zu Memory-Leaks und Doppel-Timern.
  • Startwert "" statt undefined, sonst wechselt das Feld zwischen uncontrolled und controlled.
  • Error Boundaries greifen nicht bei async-Code oder Event-Handlern.

Forge

  • forge deploy vergessenforge install nutzt den alten Stand.
  • Neue Rechte (z. B. storage) müssen ins Manifest und neu installiert werden; auch ausgehende Netzwerkaufrufe brauchen eine Freigabe.
  • manifest.yml ist YAML — Leerzeichen einrücken, keine Tabs.
  • resource.path zeigt ins Leere → das Frontend lädt nicht.
  • storage.set ist asynchron — Promise zurückgeben oder await.
  • Nicht jede Node-Bibliothek läuft in der Forge-Sandbox.
  • UI Kit und Custom UI nicht im selben Modul vermischen.

Zum Seminar React-Schulung für Atlassian Forge