Einführung
Wir entwickeln eine einfache Chat-Anwendung mit ReactJS auf Basis des bereits implementierten Servers. Zunächst erstellen wir statische Komponenten, die anschließend mit dem Zustand verknüpft werden. Im letzten Schritt abonnieren wir den Ereignisserver.
Voraussetzungen
- Grundkenntnisse in JavaScript und ReactJS (ich versuche, es einfach zu halten).
- npm v6
- npx v6
- Node v12
Schritt 1: Projekt starten
Führen Sie in Ihrem Projektordner den Befehl `npx create-react-app --use-npm simple-chat-app` aus und warten Sie, bis die Installation abgeschlossen ist. Dadurch werden alle notwendigen Abhängigkeiten hinzugefügt und eine einfache Entwicklung und ein unkomplizierter Build-Prozess ermöglicht.
Fügen Sie die folgenden Dateien zum src-Ordner hinzu:
- App.js (sollte bereits existieren)
- ChatLineHolder.js
- ChatLine.js
- ChatInput.js
Führen Sie im Projektordner in Ihrer Konsole den Befehl `npm run start` aus. Dadurch wird ein Entwicklungsserver gestartet und die Anwendung in Ihrem Standardbrowser geöffnet.
Im src-Ordner sollte bereits eine App.js-Datei vorhanden sein. Sie können vorerst alle von ihr zurückgegebenen Informationen löschen und nur diese eine Datei behalten. <div> Schick es zurück.
const App = () => {
return <div className='chat-app'></div>
}Wir beginnen damit, unsere Komponenten von unten nach oben zu erstellen.
Schritt 2: Komponente
In ChatLine.js erstellen wir eine neue Komponente mit zwei Eigenschaften:
Name: ZeichenketteNachricht: Zeichenkette
Dies sind die Daten, die wir später vom Server als Ereignisdaten erhalten werden.
Komponente Eins
import React from 'react'
const ChatLine = ({ name, message }) => {
return (
<li>
{name}: {message}
</li>
)
}
export defaultHinweis: ReactJS verhindert automatisch HTML-Injection, Sie brauchen sich also keine Sorgen zu machen.
Schritt 3: Komponente
In ChatHolder.js erstellen wir eine neue Komponente, die nur eine Basisklasse benötigt:
Zeilen: Array<{ name: string, message: string }>
Wenn Linien Wenn das Feld leer ist, zeigen wir eine einfache Benachrichtigung an.
if (lines.length === 0) {
return <div>Chat history is empty</div>
}`Lines` ist ein Array von Objekten. Jedes Objekt besitzt einen Namen und die Eigenschaft `message`. Wir durchlaufen alle Elemente des Arrays, um das Ergebnis zu erhalten, indem wir den Namen und die Zeichenkette an die Komponente übergeben. Erstelle mehrere ChatLine-Knoten.
const chatLines = lines.map(
(line, index) => (
<ChatLine key={index} name={line.name} message={line.message} />
)
)Dann das Ergebnis in einem
- Wir rendern die Komponente und erhalten so das fertige Ergebnis:
- onSend: (message: string) => void
- Name: Der Name des Benutzers, der chattet.
- chatLines: Ein Array, das den Chatverlauf darstellt.
- eventListener: Wird verwendet, um Ereignisse vom Server zu verwalten. (Hinweis: Ich habe mich entschieden, den Listener in den entsprechenden Teil einzufügen.).
- Nachricht an Server senden
- Abonnieren Sie die vom Server gesendeten Ereignisse.
import React from 'react'
import ChatLine from './ChatLine'
const ChatLineHolder = ({ lines }) => {
if (lines.length === 0) {
return <div>Chat history is empty</div>
}
const chatLines = lines.map(
(line, index) => (
<ChatLine key={index} message={line.message} name={line.name} />
)
)
return (
<ul>
{chatLines}
</ul>
)
}
export default ChatLineHolderHinweis: Normalerweise verwendet man einen eindeutigen Bezeichner als Schlüssel. In diesem Fall können wir bedenkenlos den Index verwenden, da sich die Zuordnung zwischen Index und Objekt nicht ändert. In realen Anwendungen ist dies jedoch sehr ärgerlich.
Schritt 4: Komponente
Wie Sie vielleicht bemerkt haben, gibt es immer noch keine Möglichkeit, Nachrichten zu importieren. Verarbeitet Texteingaben und verwendet beim Absenden eine Callback-Funktion, um beim Klicken auf den Button eine neue Chatnachricht zu öffnen. Erfordert eine Prop:
Die Benutzereingabekomponente behält ihren Zustand bei und verwaltet Aktualisierungen.
const [value, setValue] = useState('')
const onChange = (event) => {
setValue(event.target.value)
}Beim Klicken auf den Absenden-Button wird die Funktion `onSend` mit dem aktuellen Zustand aufgerufen. Da wir nicht möchten, dass der Benutzer das Eingabefeld manuell leeren muss, setzen wir den Zustand nach dem Aufruf von `onSend` zurück.
const onClickSend = () => {
onSend(value)
setValue('')
}
Hier ist die letzte Komponente:
import React, { useState } from 'react'
const ChatInput = ({ onSend }) => {
const [value, setValue] = useState('')
const onChange = (event) => {
setValue(event.target.value)
}
const onClickSend = () => {
setValue('')
onSend(value)
}
return (
<div>
<input type='text' value={value} onChange={onChange} />
<button onClick={onClickSend}>send</button>
</div>
)
}
export default ChatInputSchritt 5: Komponente
Modus
Da unsere Komponenten keine Daten speichern, Als Hauptkomponente verwenden wir sie zur Zustandsverwaltung. Wir haben 3 Arten von Zuständen:
(Der Einfachheit halber wäre in einer realen Anwendung möglicherweise ein anderer Ansatz ratsam.)
Wir verwenden State Hooks, um unseren Zustand zu initialisieren:
const [chatLines, setChatLines] = useState([])
const [eventListener, setEventListener] = useState(null)
const [name] = useState(generateRandomName())Komponenten-Rendering-Test
Im Moment zeigen wir nur unseren Namen und die Komponente an. Wir präsentieren den Chatzeilen feste Elemente. Da Chatzeilen ein leeres Array ist, muss unsere Benachrichtigung bereitgestellt werden. Wir rufen eine leere Flash-Funktion auf, um Wir werden es senden. Die Ausführung erfolgt im nächsten Schritt.
return (
<div className='chat-app'>
<h2>Chatting as {name}</h2>
<ChatLineHolder lines={chatLines} />
<ChatInput onSend={() => {}} />
</div>
)Wenn Sie überprüfen möchten, ob Ihre Implementierung mit einigen Daten funktioniert, fügen Sie einfach ein paar Elemente zu chatLines hinzu.
const [chatLines, setChatLines] = useState([{ name: 'Thomas', 'message': 'Hi' }])
Interaktion hinzufügen
Wir können bereits Text in unser Chat-Eingabefeld eingeben, aber das Drücken von „Senden“ bewirkt nichts. Das liegt daran, dass wir eine Funktion namens „…“ haben. Wir haben etwas gesendet, das absolut nichts bewirkt. Daher benötigen wir eine Implementierung dafür.
Da wir noch nicht mit unserem Server verbunden sind, implementieren wir unsere onSend-Methode so, dass der Zustand direkt aktualisiert wird. Dazu fügen wir die Hilfsfunktion addChatLine: (chatLine) => void hinzu. Diese verwenden wir später, um vom Server gesendete Nachrichtenereignisse zu verarbeiten.
const addChatLine = (chatLine) => {
setChatLines(chatLines => {
return [...chatLines, chatLine]
})
// If you don't have a lot of experience with ReactJS, just think of this as:
// setChatLines([...chatLines, chatLine])
}onSend erstellt ein Chatline-Objekt und ruft addChatLine auf.
const onSend = (message) => {
const chatLine = { name, message }
addChatLine(chatLine)
}Vergiss nicht, es zu senden an Schicken.
return (
<div className='chat-app'>
<h2>Chatting as {name}</h2>
<ChatLineHolder lines={chatLines} />
<ChatInput onSend={onSend} />
</div>
)Sie sollten nun in der Lage sein, Text in das Eingabefeld einzugeben, auf „Senden“ zu klicken und Ihre Nachricht sofort zu sehen.
Schritt 6: Verbindung zum Server herstellen
Sich selbst zu unterhalten ist sehr langweilig. Deshalb müssen wir unsere Anwendung mit dem Server verbinden. Dies geschieht in zwei Schritten:
Nachricht an Server senden
Wir müssen die von uns geschriebene onSend-Funktion anpassen. Wir können den gesamten Body durch einen einfachen Fetch-Aufruf ersetzen, der unseren Namen und unsere Nachricht im Body sendet. Wichtig ist, addChatLine nicht aufzurufen, da wir dies später tun, sobald wir das vom Server gesendete Ereignis empfangen.
const onSend = async (message) => {
fetch('http://localhost:4000/say',
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'post',
mode: 'no-cors',
body: `name=${name}&message=${message}`
})
}Wenn Sie jetzt auf „Absenden“ klicken, wird eine Anfrage an den Server gesendet, Ihr Status wird aber noch nicht aktualisiert! Wir kümmern uns im nächsten Schritt darum.
Abonnieren Sie die vom Server gesendeten Ereignisse.
Bevor wir Ereignisse abfangen, benötigen wir eine Funktion, die solche Nachrichtenereignisse verarbeitet. Da wir später Nachrichtenereignisse abfangen werden, können wir sie entsprechend implementieren. Sie nimmt einfach `event.data` entgegen, parst es in ein Objekt und ruft `addChatLine` auf.
const onMessage = (event) => {
const chatLine = JSON.parse(event.data)
addChatLine(chatLine)
}
Um vom Server gesendete Ereignisse zu empfangen, erstellen wir ein Objekt der Klasse `EventSource` mit unserer lokalen Adresse. Anschließend fügen wir einen Ereignis-Listener für den Nachrichtentyp hinzu. Dann umschließen wir ihn mit einem `useEffect`-Hook (dies stellt sicher, dass die Komponente beim Aufruf von `useEffect` ausgelöst wird). Es wird eingebunden, die Ereignisquelle wird initialisiert und anschließend wieder geschlossen.
useEffect(() => {
let source = new EventSource('http://localhost:4000/listen')
source.addEventListener('message', onMessage)
setEventSource(source)
return () => { source.close() }
}, [])Komponente Schließlich sieht es so aus:
import React, { useEffect, useState } from 'react'
import ChatLineHolder from './ChatLineHolder'
import ChatInput from './ChatInput'
const App = () => {
const [chatLines, setChatLines] = useState([])
const [eventSource, setEventSource] = useState(null)
const [name] = useState(generateRandomName())
const addChatLine = (chatLine) => {
setChatLines(chatLines => [...chatLines, chatLine])
}
const onMessage = (event) => {
const chatLine = JSON.parse(event.data)
addChatLine(chatLine)
}
useEffect(() => {
let source = new EventSource("http://localhost:4000/listen")
source.addEventListener('message', onMessage)
setEventSource(source)
return () => { source.close() }
}, [])
const onSend = (message) => {
fetch(
`http://localhost:4000/say`,
{
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
method: "post",
mode: 'no-cors',
body: `name=${name}&message=${message}`,
})
}
return (
<div className='chat-app'>
<h2>Chatting as {name}</h2>
<ChatLineHolder lines={chatLines} />
<ChatInput onSend={onSend} />
</div>
)
}
export default AppErgebnis
Jetzt können Sie Ihre Seite in zwei Tabs öffnen und mit zwei Alter Egos chatten! Sie können die App-Komponente auch zweimal einbinden (indem Sie die index.js-Datei ändern), da jede Instanz ihren eigenen Zustand hat.









