Eine CBT-App entwickeln: Datenstrukturen & React State Management
Erkunden Sie die technische Architektur hinter Mental-Health-Apps. Erfahren Sie, wie Sie CBT-Übungen für Ihre Datenbank modellieren, komplexe mehrstufige Benutzerabläufe in React mit useReducer verwalten und sicherstellen, dass Ihre Anwendung sicher und skalierbar ist.
Auf dieser Seite
Der Markt für Apps für psychische Gesundheit boomt und wird voraussichtlich deutlich wachsen, da immer mehr Menschen zugängliche Unterstützung suchen. Viele dieser Apps basieren auf Prinzipien der Kognitiven Verhaltenstherapie (KVT), einer Technik, die Menschen dabei hilft, destruktive Denkmuster zu erkennen und zu verändern.
Auf den ersten Blick könnte eine KVT-App wie eine einfache Formular-Daten-Anwendung erscheinen. Aber wie führen Sie einen Benutzer durch eine strukturierte, mehrstufige therapeutische Übung wie ein „Gedankenprotokoll"? Wie verwalten Sie den komplexen Zustand, während der Benutzer reflektiert und zutiefst persönliche Daten eingibt? Dies ist keine weitere To-Do-Listen-App.
In diesem Deep Dive werden wir eine vereinfachte, aber leistungsstarke KVT-„Gedankenprotokoll"-Funktion mit React erstellen. Wir werden untersuchen, wie wir die Daten modellieren, ein robustes mehrstufiges Formular aufbauen und seinen Zustand effektiv verwalten. Dieser Artikel richtet sich an Entwickler, die sich für die Schnittstelle zwischen psychischer Gesundheit und Technologie interessieren, oder an jeden, der seine Fähigkeiten in der Verwaltung komplexer Zustände in React verbessern möchte.
Voraussetzungen:
- Solides Verständnis von React (einschließlich Hooks wie
useStateunduseEffect). - Grundkenntnisse in Datenbankkonzepten (relational vs. NoSQL).
- Node.js und npm/yarn installiert.
Das Problem verstehen: Das Gedankenprotokoll
Ein Grundpfeiler der KVT ist das „Gedankenprotokoll". Es ist eine strukturierte Übung, die Benutzern hilft, ängstliche oder negative Gedanken zu zerlegen. Ein typischer Ablauf sieht folgendermaßen aus:
- Situation: Beschreiben Sie das Ereignis, das den Gedanken ausgelöst hat.
- Automatische Gedanken: Was war der unmittelbare Gedanke oder das Bild, das Ihnen in den Sinn kam?
- Emotionen: Welche Emotionen hat dieser Gedanke hervorgerufen? (z.B. Traurigkeit, Angst). Bewerten Sie deren Intensität.
- Belege dafür: Welche Fakten unterstützen diesen automatischen Gedanken?
- Belege dagegen: Welche Fakten widersprechen diesem automatischen Gedanken?
- Alternativer Gedanke: Erstellen Sie einen ausgewogeneren oder realistischeren Gedanken.
- Ergebnis: Bewerten Sie die Intensität der ursprünglichen Emotionen erneut.
Dieser mehrstufige, sequenzielle Prozess ist eine perfekte Fallstudie für eine technische Herausforderung. Wir müssen:
- Den Benutzer von einem Schritt zum nächsten führen.
- Es ihm ermöglichen, zurückzugehen und frühere Antworten zu ändern.
- Den gesamten Protokolleintrag im Zustand halten, bis er abgeschlossen ist.
- Den finalen Protokolleintrag strukturiert in einer Datenbank speichern.
Schritt 1: Modellierung der Datenstruktur
Bevor wir eine einzige Zeile React schreiben, müssen wir unsere Datenstruktur definieren. Eine gut gestaltete Struktur wird die Zustandsverwaltung und Datenspeicherung viel einfacher machen. Wir können den Gedankenprotokolleintrag als ein einzelnes Objekt modellieren.
Das Datenmodell
Hier ist ein JavaScript-Objekt, das einen vollständigen Gedankenprotokolleintrag repräsentiert.
// src/data/thoughtRecordModel.js
const thoughtRecord = {
id: 'uuid-1234',
userId: 'user-abc',
createdAt: '2025-12-11T10:00:00Z',
situation: 'Ich habe einen Fehler in meiner Präsentation bei der Arbeit gemacht.',
automaticThoughts: 'Jeder denkt, ich bin inkompetent.',
initialEmotions: [
{ name: 'Angst', intensity: 8 },
{ name: 'Scham', intensity: 7 }
],
evidenceFor: 'Ein Kollege wies auf den Fehler hin.',
evidenceAgainst: 'Mein Vorgesetzter sagte, der Rest der Präsentation war großartig. Ich habe zuvor positives Feedback erhalten.',
alternativeThought: 'Einen Fehler zu machen ist menschlich. Es definiert nicht meine Gesamtkompetenz. Ich kann daraus lernen.',
outcomeEmotions: [
{ name: 'Angst', intensity: 3 },
{ name: 'Scham', intensity: 2 }
],
isComplete: true,
};
Datenbankschema-Design
Diese Struktur kann auf verschiedene Datenbanktypen abgebildet werden.
1. Relationale Datenbank (z.B. PostgreSQL)
Sie hätten wahrscheinlich einige Tabellen.
users
id(PK)emailpassword_hash
thought_records
id(PK)user_id(FK zu users.id)created_atsituation(TEXT)automatic_thoughts(TEXT)evidence_for(TEXT)evidence_against(TEXT)alternative_thought(TEXT)is_complete(BOOLEAN)
emotions
id(PK)record_id(FK zu thought_records.id)name(VARCHAR)intensity(INTEGER)type(ENUM: 'initial', 'outcome')
2. NoSQL-Datenbank (z.B. MongoDB)
Bei einer dokumentenbasierten Datenbank bildet unser JavaScript-Modell fast direkt auf ein einzelnes Dokument in einer thoughtRecords-Sammlung ab. Diese Einfachheit ist oft eine großartige Wahl für diese Art von verschachtelten Daten.
{
"_id": ObjectId("..."),
"userId": ObjectId("..."),
"createdAt": ISODate("..."),
"situation": "Ich habe einen Fehler gemacht...",
"automaticThoughts": "Jeder denkt, ich bin inkompetent.",
"initialEmotions": [
{ "name": "Angst", "intensity": 8 },
{ "name": "Scham", "intensity": 7 }
],
// ... und so weiter
}
Für dieses Tutorial konzentrieren wir uns auf das Frontend und gehen davon aus, dass eine API diese Datenstruktur letztendlich verarbeiten wird.
Schritt 2: Architektur des Zustands mit useReducer
Für ein mehrstufiges Formular kann die Verwaltung des Zustands mit mehreren useState-Hooks chaotisch werden. Dies ist eine perfekte Aufgabe für den useReducer-Hook. Er zentralisiert unsere Zustandslogik, macht sie vorhersehbarer und einfacher zu debuggen, ähnlich dem Redux-Muster.
Definition des Zustands und der Aktionen
Lassen Sie uns einen Reducer erstellen, um unser Gedankenprotokoll-Formular zu verwalten.
// src/hooks/useThoughtRecord.js
export const initialState = {
step: 1, // Aktueller Schritt im Formular
record: {
situation: '',
automaticThoughts: '',
initialEmotions: [],
evidenceFor: '',
evidenceAgainst: '',
alternativeThought: '',
outcomeEmotions: [],
},
isComplete: false,
};
export function thoughtRecordReducer(state, action) {
switch (action.type) {
case 'NEXT_STEP':
return { ...state, step: state.step + 1 };
case 'PREVIOUS_STEP':
return { ...state, step: state.step - 1 };
case 'UPDATE_FIELD':
return {
...state,
record: {
...state.record,
[action.payload.field]: action.payload.value,
},
};
case 'SUBMIT':
return { ...state, isComplete: true };
case 'RESET':
return initialState;
default:
throw new Error('Unhandled action type');
}
}
Wie es funktioniert
initialState: Definiert die Form unseres Zustands, einschließlich des aktuellenstepund derrecord-Daten.thoughtRecordReducer: Diese reine Funktion nimmt den aktuellenstateund eineactionund gibt den neuen Zustand zurück.NEXT_STEP/PREVIOUS_STEP: Einfache Übergänge, die einfach die Schrittnummer erhöhen oder verringern.UPDATE_FIELD: Eine flexible Aktion, um ein beliebiges Feld in unseremrecord-Objekt zu aktualisieren.SUBMIT: Markiert den Prozess als abgeschlossen.
Schritt 3: Aufbau der mehrstufigen Formularkomponenten
Jetzt bauen wir die React-Komponenten. Wir haben eine Hauptkomponente ThoughtRecordFlow, die unseren Reducer verwendet, und sie wird bedingt die Komponente für den aktuellen Schritt rendern.
Die Hauptflusskomponente
// src/components/ThoughtRecordFlow.js
import React, { useReducer } from 'react';
import { initialState, thoughtRecordReducer } from '../hooks/useThoughtRecord';
// Step-Komponenten importieren (eine davon werden wir als nächstes erstellen)
import Step1_Situation from './steps/Step1_Situation';
import Step2_AutomaticThoughts from './steps/Step2_AutomaticThoughts';
// ... weitere Step-Komponenten
const ThoughtRecordFlow = () => {
const [state, dispatch] = useReducer(thoughtRecordReducer, initialState);
const { step, record } = state;
const renderStep = () => {
switch (step) {
case 1:
return <Step1_Situation record={record} dispatch={dispatch} />;
case 2:
return <Step2_AutomaticThoughts record={record} dispatch={dispatch} />;
// ... Fälle für weitere Schritte
default:
return <Step1_Situation record={record} dispatch={dispatch} />;
}
};
return (
<div className="cbt-flow-container">
<h2>Gedankenprotokoll - Schritt {step} von 7</h2>
{renderStep()}
</div>
);
};
export default ThoughtRecordFlow;
Diese Komponente fungiert als unsere Zustandsverwaltung und Router für die Formularschritte.
Eine Beispiel-Step-Komponente
Lassen Sie uns sehen, wie Step1_Situation.js aussehen würde.
// src/components/steps/Step1_Situation.js
import React from 'react';
const Step1_Situation = ({ record, dispatch }) => {
const { situation } = record;
const handleChange = (e) => {
dispatch({
type: 'UPDATE_FIELD',
payload: { field: 'situation', value: e.target.value },
});
};
const handleNext = () => {
// Optional: Validierung hier hinzufügen
if (situation.trim()) {
dispatch({ type: 'NEXT_STEP' });
}
};
return (
<div className="step-container">
<p>Beschreiben Sie die Situation, die Ihren schwierigen Gedanken ausgelöst hat.</p>
<textarea
value={situation}
onChange={handleChange}
placeholder="z.B., Ich hielt eine Präsentation und mein Geist wurde leer."
/>
<div className="navigation-buttons">
<button onClick={handleNext} disabled={!situation.trim()}>
Weiter →
</button>
</div>
</div>
);
};
export default Step1_Situation;
Wie es funktioniert
- Die Komponente empfängt den aktuellen
record-Zustand und diedispatch-Funktion als Props. - Das
textareaist eine kontrollierte Komponente, deren Wert anrecord.situationgebunden ist. - Bei jeder Änderung wird eine
UPDATE_FIELD-Aktion dispatched. - Der „Weiter"-Button dispatched die
NEXT_STEP-Aktion, um den Fluss fortzusetzen.
Sie würden ähnliche Komponenten für jeden Schritt des Gedankenprotokolls erstellen, von denen jede ihr eigenes Stück des Zustands über den zentralisierten Reducer verwaltet.
Alternative Herangehensweise: Endliche Zustandsautomaten
Unsere useReducer-Implementierung ist hervorragend, aber wenn Abläufe komplexer werden (z.B. bedingte Schritte, verschiedene Benutzerpfade), kann es von Vorteil sein, einen endlichen Zustandsautomaten (FSM) zu verwenden.
Ein FSM ist ein Modell, bei dem sich eine Anwendung zu einem bestimmten Zeitpunkt in nur einem von einer endlichen Anzahl von Zuständen befinden kann. Ein Übergang von einem Zustand in einen anderen wird durch ein Ereignis ausgelöst.
Dies beschreibt perfekt unsere KVT-Übung!
- Zustände:
willkommen,situationSchreiben,gedankenIdentifizieren,inFrageStellen,abschließen. - Ereignisse:
UEBUNG_STARTEN,WEITER,ZURÜCK,ENTWURF_SPEICHERN.
Bibliotheken wie XState ermöglichen es Ihnen, diese Abläufe deklarativ zu definieren.
// Eine konzeptuelle XState-Maschinendefinition
import { createMachine } from 'xstate';
const thoughtRecordMachine = createMachine({
id: 'thoughtRecord',
initial: 'situation',
context: { /* unsere Aufzeichnungsdaten kommen hierher */ },
states: {
situation: {
on: { NEXT: 'automaticThoughts' }
},
automaticThoughts: {
on: { NEXT: 'initialEmotions', PREVIOUS: 'situation' }
},
// ... weitere Zustände
}
});
Warum einen Zustandsautomaten verwenden?
- Klarheit: Der gesamte Benutzerfluss ist an einem Ort definiert.
- Sicherheit: Er verhindert unmögliche Zustandsübergänge (z.B. das Überspringen eines Schritts).
- Visualisierung: Sie können automatisch visuelle Diagramme Ihrer Benutzerflüsse aus der Maschinendefinition generieren, was fantastisch für Dokumentation und Teamkommunikation ist.
Best Practices für Sicherheit
Beim Aufbau einer App für psychische Gesundheit sind Sicherheit und Datenschutz keine optionalen Funktionen – sie sind das Fundament des Benutzervertrauens. Der unsachgemäße Umgang mit sensiblen Daten kann schwerwiegende Folgen haben.
- Compliance: Beachten Sie Vorschriften wie HIPAA (in den USA) und DSGVO (in der EU). Diese haben strenge Regeln für den Umgang mit geschützten Gesundheitsinformationen (PHI).
- Datenverschlüsselung: Alle Daten müssen bei der Übertragung (mit HTTPS/TLS) und bei der Speicherung (durch Verschlüsselung der Datenbank selbst) verschlüsselt werden.
- Authentifizierung & Autorisierung: Verwenden Sie robuste Authentifizierungsmethoden (z.B. OAuth 2.0). Stellen Sie sicher, dass ein Benutzer nur jemals auf seine eigenen Daten zugreifen kann.
- Anonymität: Ermöglichen Sie Benutzern, wann immer möglich, die Nutzung von Funktionen ohne Bereitstellung unnötiger persönlich identifizierbarer Informationen (PII).
- Transparente Datenschutzrichtlinien: Erklären Sie klar, welche Daten Sie sammeln und wie sie verwendet werden.
Fazit
Wir haben erfolgreich eine komplexe therapeutische Übung in eine handhabbare und skalierbare technische Architektur zerlegt. Durch den Start mit einem klaren Datenmodell, die Nutzung von Reacts useReducer für die zentralisierte Zustandsverwaltung und die Strukturierung unserer UI in diskrete Schritte haben wir die Grundlage für eine leistungsstarke und verantwortungsvolle KVT-Anwendung geschaffen.
Sie haben gelernt:
- Einen realen, mehrstufigen Prozess in eine saubere Datenstruktur zu modellieren.
- Ein robustes mehrstufiges Formular mit
useReducerzu implementieren. - Zu erkennen, wann eine Finite-Zustandsmaschine ein besseres Werkzeug sein könnte.
- Die kritischen Sicherheits- und Datenschutzimplikationen beim Aufbau von Technologie für psychische Gesundheit zu berücksichtigen.
Der nächste Schritt ist, dieses Frontend mit einer sicheren Backend-API zu verbinden, die Daten zu persistieren und ein Dashboard für Benutzer zu erstellen, um ihre vergangenen Gedankenprotokolle zu überprüfen.
Ressourcen
- React Docs: Zustandsverwaltung
- XState: JavaScript-Zustandsmaschinen und Statecharts
- PostgreSQL: Offizielle Dokumentation
- MongoDB: Offizielle Dokumentation
Kurzübersicht
| Aspekt | Wichtige Informationen |
|---|---|
| Thema | Entwicklung |
| Relevanz | Patientenaufklärung und -sensibilisierung |
| Maßnahme | Besprechen Sie dies mit Ihrem medizinischen Fachpersonal |
| Häufigkeit | Wie von Ihrem Behandlungsteam empfohlen |
| Evidenz | Basierend auf aktuellen klinischen Richtlinien |
Häufig gestellte Fragen
F: Woher weiß ich, ob dies auf mich zutrifft? A: Besprechen Sie Ihre persönliche und familiäre Krankengeschichte mit Ihrem medizinischen Fachpersonal, um Ihre individuellen Risikofaktoren zu bewerten und geeignete nächste Schritte zu bestimmen.
F: Was sollte ich meinen Arzt fragen? A: Gute Fragen sind unter anderem: „Was bedeuten meine Ergebnisse?", „Was sind meine Optionen?", „Welche Lebensstiländerungen würden helfen?" und „Wann sollte ich nachbeobachten?"
F: Gibt es Lebensstiländerungen, die helfen können? A: Die meisten Erkrankungen profitieren von grundlegenden Maßnahmen: ausgewogene Ernährung, regelmäßige körperliche Aktivität (150+ Minuten/Woche), erholsamer Schlaf (7-9 Stunden), Stressmanagement und Vermeidung von Tabak.
Haftungsausschluss
Dieser Artikel dient nur zu Bildungszwecken und stellt keine medizinische Beratung dar. Konsultieren Sie immer einen qualifizierten medizinischen Fachmann, bevor Sie Entscheidungen über Ihre Gesundheit, Behandlung oder Pflege treffen. Individuelle Umstände variieren, und was für eine Person angemessen ist, ist möglicherweise nicht für eine andere Person geeignet.
Wenn Sie einen medizinischen Notfall erleben, rufen Sie sofort 911 (oder Ihre örtliche Notrufnummer) an.