Μετατροπή ομιλίας σε PDF με NextJS και ExpressJS PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Μετατροπή ομιλίας σε PDF με NextJS και ExpressJS

Καθώς οι διεπαφές ομιλίας γίνονται όλο και περισσότερο θέμα, αξίζει να εξερευνήσετε μερικά από τα πράγματα που μπορούμε να κάνουμε με τις αλληλεπιδράσεις ομιλίας. Τι θα γινόταν αν μπορούσαμε να πούμε κάτι και να μεταγραφεί και να κυκλοφορήσει ως PDF με δυνατότητα λήψης;

Λοιπόν, spoiler alert: εμείς απολύτως κουτί Κάνε αυτό! Υπάρχουν βιβλιοθήκες και πλαίσια που μπορούμε να συνδυάσουμε για να το πετύχουμε, και αυτό θα κάνουμε μαζί σε αυτό το άρθρο.

Αυτά είναι τα εργαλεία που χρησιμοποιούμε

Πρώτα απ 'όλα, αυτοί είναι οι δύο μεγάλοι παίκτες: Next.js και Express.js.

Next.js επιβάλλει πρόσθετες λειτουργίες στο React, συμπεριλαμβανομένων βασικών λειτουργιών για τη δημιουργία στατικών τοποθεσιών. Είναι μια επιλογή για πολλούς προγραμματιστές λόγω των όσων προσφέρει αμέσως, όπως δυναμική δρομολόγηση, βελτιστοποίηση εικόνας, δρομολόγηση ενσωματωμένου τομέα και υποτομέα, γρήγορες ανανεώσεις, δρομολόγηση συστήματος αρχείων και διαδρομές API... πολλά, πολλά άλλα πράγματα.

Στην περίπτωσή μας, χρειαζόμαστε οπωσδήποτε το Next.js για αυτό Διαδρομές API στον διακομιστή πελάτη μας. Θέλουμε μια διαδρομή που παίρνει ένα αρχείο κειμένου, το μετατρέπει σε PDF, το γράφει στο σύστημα αρχείων μας και μετά στέλνει μια απάντηση στον πελάτη.

Express.js μας επιτρέπει να χρησιμοποιήσουμε μια μικρή εφαρμογή Node.js με δρομολόγηση, βοηθούς HTTP και πρότυπα. Είναι ένας διακομιστής για το δικό μας API, που είναι αυτό που θα χρειαστούμε καθώς περνάμε και αναλύουμε δεδομένα μεταξύ των πραγμάτων.

Έχουμε κάποιες άλλες εξαρτήσεις που θα χρησιμοποιήσουμε:

  1. αντίδραση-ομιλία-αναγνώριση: Μια βιβλιοθήκη για τη μετατροπή ομιλίας σε κείμενο, καθιστώντας τη διαθέσιμη στα στοιχεία του React.
  2. αναγεννητής-χρόνος λειτουργίας: Μια βιβλιοθήκη για την αντιμετώπιση προβλημάτων του "regeneratorRuntime δεν είναι ορισμένο» που εμφανίζεται στο Next.js όταν χρησιμοποιείται το react-speech-recognition
  3. html-pdf-node: Μια βιβλιοθήκη για τη μετατροπή μιας σελίδας HTML ή μιας δημόσιας διεύθυνσης URL σε PDF
  4. αξίους: Μια βιβλιοθήκη για την υποβολή αιτημάτων HTTP τόσο στο πρόγραμμα περιήγησης όσο και στο Node.js
  5. κέρατα: Μια βιβλιοθήκη που επιτρέπει την κοινή χρήση πόρων μεταξύ προέλευσης

Εγκαθιστώ

Το πρώτο πράγμα που θέλουμε να κάνουμε είναι να δημιουργήσουμε δύο φακέλους έργου, έναν για τον πελάτη και έναν για τον διακομιστή. Ονομάστε τους όπως θέλετε. Ονομάζω το δικό μου audio-to-pdf-client και audio-to-pdf-server, Αντίστοιχα.

Ο πιο γρήγορος τρόπος για να ξεκινήσετε με το Next.js στην πλευρά του πελάτη είναι να το κάνετε bootstrap δημιουργία-επόμενη-εφαρμογή. Επομένως, ανοίξτε το τερματικό σας και εκτελέστε την ακόλουθη εντολή από το φάκελο του έργου πελάτη σας:

npx create-next-app client

Τώρα χρειαζόμαστε τον διακομιστή Express μας. Μπορούμε να τα βγάλουμε πέρα cd-μπαίνετε στο φάκελο του έργου διακομιστή και εκτελείτε το npm init εντολή. ΕΝΑ package.json το αρχείο θα δημιουργηθεί στο φάκελο του έργου διακομιστή μόλις ολοκληρωθεί.

Πρέπει ακόμα να εγκαταστήσουμε το Express, οπότε ας το κάνουμε τώρα με npm install express. Τώρα μπορούμε να δημιουργήσουμε ένα νέο index.js αρχείο στο φάκελο του έργου διακομιστή και αποθέστε αυτόν τον κώδικα εκεί:

const express = require("express")
const app = express()

app.listen(4000, () => console.log("Server is running on port 4000"))

Είστε έτοιμοι να εκτελέσετε τον διακομιστή;

node index.js

Θα χρειαστούμε μερικούς ακόμη φακέλους και άλλο ένα αρχείο για να προχωρήσουμε:

  • Δημιουργία components φάκελο στο φάκελο του έργου πελάτη.
  • Δημιουργία SpeechToText.jsx αρχείο στο components υποφάκελος.

Πριν προχωρήσουμε περαιτέρω, έχουμε ένα μικρό καθαρισμό να κάνουμε. Συγκεκριμένα, πρέπει να αντικαταστήσουμε τον προεπιλεγμένο κωδικό στο pages/index.js αρχείο με αυτό:

import Head from "next/head";
import SpeechToText from "../components/SpeechToText";

export default function Home() {
  return (
    <div className="home">
      <Head>
        <title>Audio To PDF</title>
        <meta
          name="description"
          content="An app that converts audio to pdf in the browser"
        />
        <link rel="icon" href="/el/favicon.ico" />
      </Head>

      <h1>Convert your speech to pdf</h1>

      <main>
        <SpeechToText />
      </main>
    </div>
  );
}

Το εισαγόμενο SpeechToText το στοιχείο θα εξαχθεί τελικά από components/SpeechToText.jsx.

Ας εγκαταστήσουμε τις άλλες εξαρτήσεις

Εντάξει, δεν έχουμε την αρχική ρύθμιση για την εφαρμογή μας. Τώρα μπορούμε να εγκαταστήσουμε τις βιβλιοθήκες που χειρίζονται τα δεδομένα που διαβιβάζονται.

Μπορούμε να εγκαταστήσουμε τις εξαρτήσεις πελατών μας με:

npm install react-speech-recognition regenerator-runtime axios

Οι εξαρτήσεις των διακομιστών Express είναι οι επόμενες, οπότε ας πάμε cd στον φάκελο του έργου διακομιστή και εγκαταστήστε τα:

npm install html-pdf-node cors

Πιθανώς είναι καλή στιγμή για παύση και βεβαιωθείτε ότι τα αρχεία στους φακέλους του έργου μας είναι εντάξει. Εδώ είναι τι πρέπει να έχετε στο φάκελο του έργου πελάτη σε αυτό το σημείο:

/audio-to-pdf-web-client
├─ /components
|  └── SpeechToText.jsx
├─ /pages
|  ├─ _app.js
|  └── index.js
└── /styles
    ├─globals.css
    └── Home.module.css

Και εδώ είναι τι πρέπει να έχετε στο φάκελο του έργου διακομιστή:

/audio-to-pdf-server
└── index.js

Δημιουργία του UI

Λοιπόν, η ομιλία μας σε PDF δεν θα ήταν τόσο καλή αν δεν υπάρχει τρόπος να αλληλεπιδράσουμε μαζί της, οπότε ας φτιάξουμε ένα στοιχείο React για αυτό που μπορούμε να καλέσουμε <SpeechToText>.

Μπορείτε να χρησιμοποιήσετε πλήρως τη δική σας σήμανση. Εδώ είναι τι έχω για να σας δώσω μια ιδέα για τα κομμάτια που συνθέτουμε:

import React from "react";

const SpeechToText = () => {
  return (
    <>
      <section>
        <div className="button-container">
          <button type="button" style={{ "--bgColor": "blue" }}>
            Start
          </button>
          <button type="button" style={{ "--bgColor": "orange" }}>
            Stop
          </button>
        </div>
        <div
          className="words"
          contentEditable
          suppressContentEditableWarning={true}
        ></div>
        <div className="button-container">
          <button type="button" style={{ "--bgColor": "red" }}>
            Reset
          </button>
          <button type="button" style={{ "--bgColor": "green" }}>
            Convert to pdf
          </button>
        </div>
      </section>
    </>
  );
};

export default SpeechToText;

Αυτό το στοιχείο επιστρέφει a Θραύσμα αντίδρασης που περιέχει ένα HTML <``section``> στοιχείο που περιέχει τρία div:

  • .button-container περιέχει δύο κουμπιά που θα χρησιμοποιηθούν για την έναρξη και τη διακοπή της αναγνώρισης ομιλίας.
  • .words έχει contentEditable και suppressContentEditableWarning χαρακτηριστικά για να κάνετε αυτό το στοιχείο επεξεργάσιμο και να αποκρύψετε τυχόν προειδοποιήσεις από το React.
  • Άλλος .button-container κρατά δύο ακόμη κουμπιά που θα χρησιμοποιηθούν για την επαναφορά και τη μετατροπή της ομιλίας σε PDF, αντίστοιχα.

Το styling είναι άλλο πράγμα. Δεν θα μπω σε αυτό εδώ, αλλά μπορείτε να χρησιμοποιήσετε κάποια στυλ που έγραψα είτε ως αφετηρία για το δικό σας styles/global.css αρχείο.

Προβολή πλήρους CSS
html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}

.home {
  background-color: #333;
  min-height: 100%;
  padding: 0 1rem;
  padding-bottom: 3rem;
}

h1 {
  width: 100%;
  max-width: 400px;
  margin: auto;
  padding: 2rem 0;
  text-align: center;
  text-transform: capitalize;
  color: white;
  font-size: 1rem;
}

.button-container {
  text-align: center;
  display: flex;
  justify-content: center;
  gap: 3rem;
}

button {
  color: white;
  background-color: var(--bgColor);
  font-size: 1.2rem;
  padding: 0.5rem 1.5rem;
  border: none;
  border-radius: 20px;
  cursor: pointer;
}

button:hover {
  opacity: 0.9;
}

button:active {
  transform: scale(0.99);
}

.words {
  max-width: 700px;
  margin: 50px auto;
  height: 50vh;
  border-radius: 5px;
  padding: 1rem 2rem 1rem 5rem;
  background-image: -webkit-gradient(
    linear,
    0 0,
    0 100%,
    from(#d9eaf3),
    color-stop(4%, #fff)
  ) 0 4px;
  background-size: 100% 3rem;
  background-attachment: scroll;
  position: relative;
  line-height: 3rem;
  overflow-y: auto;
}

.success,
.error {
  background-color: #fff;
  margin: 1rem auto;
  padding: 0.5rem 1rem;
  border-radius: 5px;
  width: max-content;
  text-align: center;
  display: block;
}

.success {
  color: green;
}

.error {
  color: red;
}

Οι μεταβλητές CSS εκεί χρησιμοποιούνται για τον έλεγχο του χρώματος φόντου των κουμπιών.

Ας δούμε τις τελευταίες αλλαγές! Τρέξιμο npm run dev στο τερματικό και ελέγξτε τα.

Θα πρέπει να το δείτε στο πρόγραμμα περιήγησης όταν το επισκέπτεστε http://localhost:3000:

Μετατροπή ομιλίας σε PDF με NextJS και ExpressJS

Η πρώτη μας μετατροπή ομιλίας σε κείμενο!

Η πρώτη ενέργεια που πρέπει να κάνετε είναι να εισάγετε τις απαραίτητες εξαρτήσεις στο δικό μας <SpeechToText> συστατικό:

import React, { useRef, useState } from "react";
import SpeechRecognition, {
  useSpeechRecognition,
} from "react-speech-recognition";
import axios from "axios";

Στη συνέχεια, ελέγχουμε εάν η αναγνώριση ομιλίας υποστηρίζεται από το πρόγραμμα περιήγησης και αποδίδουμε μια ειδοποίηση εάν δεν υποστηρίζεται:

const speechRecognitionSupported =
  SpeechRecognition.browserSupportsSpeechRecognition();

if (!speechRecognitionSupported) {
  return <div>Your browser does not support speech recognition.</div>;
}

Στη συνέχεια, ας εξάγουμε transcript και resetTranscript από το useSpeechRecognition() άγκιστρο:

const { transcript, resetTranscript } = useSpeechRecognition();

Αυτό χρειαζόμαστε για το κράτος που χειρίζεται listening:

const [listening, setListening] = useState(false);

Χρειαζόμαστε επίσης ένα ref των div με contentEditable χαρακτηριστικό, τότε πρέπει να προσθέσουμε το ref αποδίδουν σε αυτό και περνούν transcript as children:

const textBodyRef = useRef(null);

…και:

<div
  className="words"
  contentEditable
  ref={textBodyRef}
  suppressContentEditableWarning={true}
  >
  {transcript}
</div>

Το τελευταίο πράγμα που χρειαζόμαστε εδώ είναι μια λειτουργία που ενεργοποιεί την αναγνώριση ομιλίας και να συνδέσει αυτή τη λειτουργία με το onClick ακροατής εκδήλωσης του κουμπιού μας. Το κουμπί ρυθμίζει την ακρόαση true και το κάνει να λειτουργεί συνεχώς. Θα απενεργοποιήσουμε το κουμπί όσο είναι σε αυτήν την κατάσταση για να μας αποτρέψει από την ενεργοποίηση πρόσθετων συμβάντων.

const startListening = () => {
  setListening(true);
  SpeechRecognition.startListening({
    continuous: true,
  });
};

…και:

<button
  type="button"
  onClick={startListening}
  style={{ "--bgColor": "blue" }}
  disabled={listening}
>
  Start
</button>

Κάνοντας κλικ στο κουμπί θα πρέπει τώρα να ξεκινήσει η μεταγραφή.

Περισσότερες λειτουργίες

Εντάξει, έχουμε λοιπόν ένα εξάρτημα που μπορεί Εκκίνηση ακούγοντας. Αλλά τώρα το χρειαζόμαστε για να κάνουμε και μερικά άλλα πράγματα, όπως stopListening, resetText και handleConversion. Ας φτιάξουμε αυτές τις λειτουργίες.

const stopListening = () => {
  setListening(false);
  SpeechRecognition.stopListening();
};

const resetText = () => {
  stopListening();
  resetTranscript();
  textBodyRef.current.innerText = "";
};

const handleConversion = async () => {}

Κάθε μία από τις λειτουργίες θα προστεθεί σε ένα onClick πρόγραμμα ακρόασης συμβάντων στα κατάλληλα κουμπιά:

<button
  type="button"
  onClick={stopListening}
  style={{ "--bgColor": "orange" }}
  disabled={listening === false}
>
  Stop
</button>

<div className="button-container">
  <button
    type="button"
    onClick={resetText}
    style={{ "--bgColor": "red" }}
  >
    Reset
  </button>
  <button
    type="button"
    style={{ "--bgColor": "green" }}
    onClick={handleConversion}
  >
    Convert to pdf
  </button>
</div>

Η handleConversion Η λειτουργία είναι ασύγχρονη επειδή τελικά θα κάνουμε ένα αίτημα API. Το κουμπί "Διακοπή" έχει το χαρακτηριστικό απενεργοποιημένο που θα ενεργοποιηθεί όταν η ακρόαση είναι ψευδής.

Εάν κάνουμε επανεκκίνηση του διακομιστή και ανανεώσουμε το πρόγραμμα περιήγησης, μπορούμε τώρα να ξεκινήσουμε, να σταματήσουμε και να επαναφέρουμε τη μεταγραφή της ομιλίας μας στο πρόγραμμα περιήγησης.

Τώρα αυτό που χρειαζόμαστε είναι να το κάνει η εφαρμογή αντιγράφω που αναγνώρισε την ομιλία μετατρέποντάς την σε αρχείο PDF. Για αυτό, χρειαζόμαστε τη διαδρομή από την πλευρά του διακομιστή από το Express.js.

Ρύθμιση της διαδρομής API

Ο σκοπός αυτής της διαδρομής είναι να λάβουμε ένα αρχείο κειμένου, να το μετατρέψουμε σε PDF, να γράψουμε αυτό το PDF στο σύστημα αρχείων μας και μετά να στείλουμε μια απάντηση στον πελάτη.

Για τη ρύθμιση, θα ανοίξαμε το server/index.js αρχείο και εισαγωγή του html-pdf-node και fs εξαρτήσεις που θα χρησιμοποιηθούν για την εγγραφή και το άνοιγμα του συστήματος αρχείων μας.

const HTMLToPDF = require("html-pdf-node");
const fs = require("fs");
const cors = require("cors)

Στη συνέχεια, θα ρυθμίσουμε τη διαδρομή μας:

app.use(cors())
app.use(express.json())

app.post("/", (req, res) => {
  // etc.
})

Στη συνέχεια, προχωράμε στον ορισμό των επιλογών που απαιτούνται για χρήση html-pdf-node εντός της διαδρομής:

let options = { format: "A4" };
let file = {
  content: `<html><body><pre style='font-size: 1.2rem'>${req.body.text}</pre></body></html>`,
};

Η options Το αντικείμενο δέχεται μια τιμή για να ορίσει το μέγεθος και το στυλ χαρτιού. Τα μεγέθη χαρτιού ακολουθούν ένα πολύ διαφορετικό σύστημα από τις μονάδες μεγέθους που χρησιμοποιούμε συνήθως στον Ιστό. Για παράδειγμα, Το Α4 είναι το τυπικό μέγεθος γράμματος.

Η file Το αντικείμενο δέχεται είτε τη διεύθυνση URL ενός δημόσιου ιστότοπου είτε τη σήμανση HTML. Για να δημιουργήσουμε τη σελίδα μας HTML, θα χρησιμοποιήσουμε το html, body, pre Ετικέτες HTML και το κείμενο από το req.body.

Μπορείτε να εφαρμόσετε οποιοδήποτε στυλ της επιλογής σας.

Στη συνέχεια, θα προσθέσουμε ένα trycatch για να χειριστείτε τυχόν σφάλματα που μπορεί να εμφανιστούν στην πορεία:

try {

} catch(error){
  console.log(error);
  res.status(500).send(error);
}

Στη συνέχεια, θα χρησιμοποιήσουμε το generatePdf από το html-pdf-node βιβλιοθήκη για τη δημιουργία α pdfBuffer (το ακατέργαστο αρχείο PDF) από το αρχείο μας και να δημιουργήσουμε ένα μοναδικό pdfName:

HTMLToPDF.generatePdf(file, options).then((pdfBuffer) => {
  // console.log("PDF Buffer:-", pdfBuffer);
  const pdfName = "./data/speech" + Date.now() + ".pdf";

  // Next code here
}

Από εκεί, χρησιμοποιούμε τη λειτουργική μονάδα συστήματος αρχείων για να γράψουμε, να διαβάσουμε και (ναι, τελικά!) να στείλουμε μια απάντηση στην εφαρμογή πελάτη:

fs.writeFile(pdfName, pdfBuffer, function (writeError) {
  if (writeError) {
    return res
      .status(500)
      .json({ message: "Unable to write file. Try again." });
  }

  fs.readFile(pdfName, function (readError, readData) {
    if (!readError && readData) {
      // console.log({ readData });
      res.setHeader("Content-Type", "application/pdf");
      res.setHeader("Content-Disposition", "attachment");
      res.send(readData);
      return;
    }

    return res
      .status(500)
      .json({ message: "Unable to write file. Try again." });
  });
});

Ας το αναλύσουμε λίγο:

  • Η writeFile Η μονάδα συστήματος αρχείων δέχεται ένα όνομα αρχείου, δεδομένα και μια λειτουργία επανάκλησης που μπορεί να επιστρέψει ένα μήνυμα σφάλματος εάν υπάρχει πρόβλημα με την εγγραφή στο αρχείο. Εάν εργάζεστε με ένα CDN που παρέχει τελικά σημεία σφάλματος, θα μπορούσατε να τα χρησιμοποιήσετε.
  • Η readFile Η μονάδα συστήματος αρχείων δέχεται ένα όνομα αρχείου και μια λειτουργία επανάκλησης που είναι ικανή ή επιστρέφει ένα σφάλμα ανάγνωσης καθώς και τα δεδομένα ανάγνωσης. Μόλις δεν έχουμε σφάλμα ανάγνωσης και υπάρχουν τα δεδομένα ανάγνωσης, θα κατασκευάσουμε και θα στείλουμε μια απάντηση στον πελάτη. Και πάλι, αυτό μπορεί να αντικατασταθεί με τα τελικά σημεία του CDN σας, εάν τα έχετε.
  • Η res.setHeader("Content-Type", "application/pdf"); λέει στο πρόγραμμα περιήγησης ότι στέλνουμε ένα αρχείο PDF.
  • Η res.setHeader("Content-Disposition", "attachment"); λέει στο πρόγραμμα περιήγησης να κάνει τα ληφθέντα δεδομένα με δυνατότητα λήψης.

Εφόσον η διαδρομή API είναι έτοιμη, μπορούμε να τη χρησιμοποιήσουμε στην εφαρμογή μας στο http://localhost:4000. Μπορούμε να προχωρήσουμε στο τμήμα πελάτη της αίτησής μας για να το ολοκληρώσουμε handleConversion λειτουργία.

Χειρισμός της μετατροπής

Πριν αρχίσουμε να εργαζόμαστε σε ένα handleConversion λειτουργία, πρέπει να δημιουργήσουμε μια κατάσταση που να χειρίζεται τα αιτήματα API για φόρτωση, σφάλματα, επιτυχία και άλλα μηνύματα. Θα χρησιμοποιήσουμε το React useState συνδέστε για να το ρυθμίσετε:

const [response, setResponse] = useState({
  loading: false,
  message: "",
  error: false,
  success: false,
});

Στο handleConversion λειτουργία, θα ελέγξουμε πότε έχει φορτωθεί η ιστοσελίδα πριν εκτελέσουμε τον κώδικά μας και θα βεβαιωθούμε ότι div με editable Το χαρακτηριστικό δεν είναι κενό:

if (typeof window !== "undefined") {
const userText = textBodyRef.current.innerText;
  // console.log(textBodyRef.current.innerText);

  if (!userText) {
    alert("Please speak or write some text.");
    return;
  }
}

Προχωράμε τυλίγοντας το ενδεχόμενο αίτημα API σε α trycatch, χειρισμός τυχόν σφάλματος που μπορεί να προκύψει και ενημέρωση της κατάστασης απόκρισης:

try {

} catch(error){
  setResponse({
    ...response,
    loading: false,
    error: true,
    message:
      "An unexpected error occurred. Text not converted. Please try again",
    success: false,
  });
}

Στη συνέχεια, ορίσαμε κάποιες τιμές για την κατάσταση απόκρισης και ορίσαμε επίσης τη διαμόρφωση για axios και κάντε ένα αίτημα ανάρτησης στον διακομιστή:

setResponse({
  ...response,
  loading: true,
  message: "",
  error: false,
  success: false,
});
const config = {
  headers: {
    "Content-Type": "application/json",
  },
  responseType: "blob",
};

const res = await axios.post(
  "http://localhost:4000",
  {
    text: textBodyRef.current.innerText,
  },
  config
);

Μόλις λάβουμε μια επιτυχημένη απάντηση, ορίζουμε την κατάσταση απόκρισης με τις κατάλληλες τιμές και δίνουμε οδηγίες στο πρόγραμμα περιήγησης να κατεβάσει το ληφθέν PDF:

setResponse({
  ...response,
  loading: false,
  error: false,
  message:
    "Conversion was successful. Your download will start soon...",
  success: true,
});

// convert the received data to a file
const url = window.URL.createObjectURL(new Blob([res.data]));
// create an anchor element
const link = document.createElement("a");
// set the href of the created anchor element
link.href = url;
// add the download attribute, give the downloaded file a name
link.setAttribute("download", "yourfile.pdf");
// add the created anchor tag to the DOM
document.body.appendChild(link);
// force a click on the link to start a simulated download
link.click();

Και μπορούμε να χρησιμοποιήσουμε τα παρακάτω κάτω από το περιεχόμενο Επεξεργάσιμο div για την εμφάνιση μηνυμάτων:

<div>
  {response.success && <i className="success">{response.message}</i>}
  {response.error && <i className="error">{response.message}</i>}
</div>

Τελικός κωδικός

Έχω συσκευάσει τα πάντα στο GitHub, ώστε να μπορείτε να δείτε τον πλήρη πηγαίο κώδικα τόσο για τον διακομιστή όσο και για τον πελάτη.

Σφραγίδα ώρας:

Περισσότερα από Κόλπα CSS