Ziel

In diesem Teil erstellen wir das React-Frontend für den Bild-Upload. Wir nutzen dafür Create React App. Darüber hinaus installieren wir Axios um XMLHttpRequests XMLHttpRequests an den Browser zu senden. Für das User Interface verwenden wir Komponenten von Material UI.

Voraussetzungen

Um die komplette Anwendung für den Bild-Upload zu implementieren, sollten Teil 1 und Teil 2 dieser Blogserie bereits implementiert sein. Für die Installation von npm-Packages muss außerdem node.js und npm installiert sein.

React-Frontend erstellen

Im Root-Verzeichnis unseres Projekts erstellen wir ein neues React-Projekt mit Create React App im Ordnerfrontend:

				
					~/projects/image-upload$ npx create-react-app frontend
				
			

Die Dateistruktur sieht danach so aus:

Bild 1: Frontend-Dateistruktur.
Bild 1: Frontend-Dateistruktur.

.env-File erstellen

Im Frontend erstellen wir nun eine .env -Datei. Dafür führen wir im Root-Verzeichnis folgenden Befehl aus:

				
					~/projects/image-upload$ touch frontend/.env
				
			
Bild 2: Frontend .env-File.
Bild 2: Frontend .env-File.

In der .env -Datei fügen wir folgende Inhalte ein:

.env
				
					REACT_APP_BACKEND_URL=http://localhost:8000
REACT_APP_API_URL=http://localhost:8000/api
REACT_APP_FRONTEND_URL=http://localhost:3000
				
			

Ähnlich wie im .env-File im Backend geben wir auch hier die URLs für Frontend und Backend ergänzt um eine API-URL an.

Axios installieren und einrichten

Mit Hilfe von npm installieren wir jetzt Axios im Frontend-Verzeichnis:

				
					~/projects/image-upload$ cd frontend && npm i axios
				
			

Im Verzeichnis src legen wir einen Ordner api:

				
					~/projects/image-upload/frontend$ mkdir src/api
				
			

Im neu erstellten Ordner src/api erstellen wir die Datei axios.js:

				
					~/projects/image-upload/frontend$ touch src/api/axios.js
				
			
Bild 3: Api-Ordner mit der Datei axios.js.
Bild 3: Api-Ordner mit der Datei axios.js.

In axios.js fügen wir folgenden Code ein:

axios.js
				
					import Axios from "axios";

const axios = Axios.create({
    baseURL: process.env.REACT_APP_API_URL,
    headers: {
        "X-Requested-With": "XMLHttpRequest",
    },
});

export default axios;
				
			

Mit obenstehenden Code haben wir eine neue Axios-Instanz erstellt. Diese Instanz verwenden wir nun in der Datei save.js:

				
					~/projects/image-upload/frontend$ touch src/api/save.js
				
			
Bild 4: Api-Ordner mit der Datei save.js.
Bild 4: Api-Ordner mit der Datei save.js.

Die Datei save.jsfüllen wir mit folgendem Inhalt:

save.js
				
					import axios from "./axios";

export const saveImage = async (image) => {
    image &&
    axios
        .post(
            `http://localhost:8000/api/save/image`,
            { image },
            {
                headers: {
                    "Content-Type": "multipart/form-data",
                },
            }
        )
        .then((response) => {
            if (response?.status === 200) {
                console.warn("Bild gespeichert!");
            }
        })
        .catch((error) => {
            if (error?.response?.status !== 422) throw error;
            console.warn(error.response.data.message);
        });
};
				
			

Material UI installieren

Für das User Interface installieren wir im nächsten Schritt Material UI. Im Verzeichnis frontend führen wir nun aus:

				
					~/projects/image-upload/frontend$ npm install @mui/material @emotion/react @emotion/styled
				
			

Als nächstes löschen wir den Inhalt der Dateisrc/App.js Im Verzeichnis Material UI führen wir nun aus:

App.js
				
					import "./App.css";
import Typography from "@mui/material/Typography";
import { Container, Button, Grid } from "@mui/material";
import { saveImage } from "../../api/save";
import { useState } from "react";

function App() {
  const [image, setImage] = useState();

  const handleFileChange = (evt) => {
    setImage(evt.target.files[0]);
  };

  return (
    <Container maxWidth="sm" sx={{ textAlign: "center" }}>
      <Typography variant="h3" component="h1">
        Image Upload
      </Typography>

      <Grid py={2}>
        <input required type="file" onChange={handleFileChange} />
      </Grid>

      <Grid py={2}>
        <Button
          variant="contained"
          onClick={() => (image ? saveImage(image) : null)}
        >
          Hochladen
        </Button>
      </Grid>
    </Container>
  );
}

export default App;
				
			

Anwendung starten

Im nächsten Schritt starten wir den Backend- und Frontend-Server.

Um den Backend-Server zu starten, wechseln wir zunächst in dasBackend -Verzeichnis:

				
					~/projects/image-upload/frontend$ cd ../backend
				
			

AnschlieĂźend fĂĽhren wir folgenden Befehl aus:

				
					~/projects/image-upload/backend$ php artisan serve
				
			

In einem weiteren Terminal-Fenster starten wir nun den Frontend-Server (vorher insFrontend-Verzeichnis wechseln):

				
					~/projects/image-upload/frontend$ npm run start
				
			

Das Frontend ist nun im Browser unter http://localhost:3000 erreichbar:

Bild 5: Frontend im Browser.
Bild 5: Frontend im Browser.

Wenn der Port 3000 bereits belegt ist, erscheint im Terminal die Frage, ob ein anderer Port genutzt werden soll:

Bild 6: Wenn der Standard-Port (3000) belegt ist, kann auf Nachfrage ein anderer Port genutzt werden.
Bild 6: Wenn der Standard-Port (3000) belegt ist, kann auf Nachfrage ein anderer Port genutzt werden.

Wir können nun den Dateiupload mit Hilfe des Frontends testen:

Bild 7: Die Datei example.png wird hochgeladen.
Bild 7: Die Datei example.png wird hochgeladen.

Nach Klick auf den Button „Hochladen“ bekommen wir eine RĂĽckmeldung in den Developer Tools:

Bild 8: Ausgabe in der Konsole der Developer Tools.
Bild 8: Ausgabe in der Konsole der Developer Tools.

In der Datenbank ist nun ein neuer Eintrag vorhanden:

Bild 9: Datenbank-Eintrag nach dem Bild-Upload.
Bild 9: Datenbank-Eintrag nach dem Bild-Upload.