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?
| Aspekt | interface | type |
|---|---|---|
| Erweitern | extends | & (Intersection) |
| Union-Types | nein | ja |
| Deklarations-Merge | ja | nein |
| Typischer Einsatz | Objektformen | Unions, 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?
| Situation | Passende Ebene |
|---|---|
| Nur eine Komponente nutzt ihn | Lokaler useState |
| Zwei Geschwister teilen ihn | In den Vorfahren heben |
| Ganzer Teilbaum braucht ihn | Context API |
| Serverdaten, Caching, Sync | Data-Library (z. B. React Query) |
Erst lokal, dann heben, dann Context — in dieser Reihenfolge.
| Pattern | Wofür |
|---|---|
| Lifting State Up | Geschwister synchron halten |
| Controlled Component | Formularwerte in React kontrollieren |
Composition (children) | Flexible, wiederverwendbare Layouts |
| Custom Hook | Logik 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
awaitliefert ein Promise statt des Werts. anybreitet sich aus und hebelt die Prüfung aus;@ts-ignoreist keine Dauerlösung.tscerzeugt trotz Typfehler Output, solangenoEmitOnErrorfehlt.- Dateien mit JSX brauchen
.tsx, nicht.ts.
React
- Der Array-Index als
keybricht bei Umsortieren oder Einfügen. {count && …}rendert bei 0 die Zahl 0 — bessercount > 0prü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
""stattundefined, sonst wechselt das Feld zwischen uncontrolled und controlled. - Error Boundaries greifen nicht bei async-Code oder Event-Handlern.
Forge
forge deployvergessen →forge installnutzt den alten Stand.- Neue Rechte (z. B.
storage) müssen ins Manifest und neu installiert werden; auch ausgehende Netzwerkaufrufe brauchen eine Freigabe. manifest.ymlist YAML — Leerzeichen einrücken, keine Tabs.resource.pathzeigt ins Leere → das Frontend lädt nicht.storage.setist asynchron — Promise zurückgeben oderawait.- Nicht jede Node-Bibliothek läuft in der Forge-Sandbox.
- UI Kit und Custom UI nicht im selben Modul vermischen.
Dieses Thema als Schulung für Ihr Team
Dieser Beitrag erklärt das Thema. Damit Ihr Team es danach auch anwendet, gibt es React-Schulung für Atlassian Forge als Schulung — an Ihrem eigenen Code, mit den Fragen, die ein Text nicht beantwortet. Sie wählen die Module, wir bauen daraus ein Programm.
4 Tage·ab 900 EUR netto pro Tag (bis 3 Teilnehmende) ·Termin nach Vereinbarung
Als Team-Schulung anfragenZum Seminar React-Schulung für Atlassian Forge →