Docuaurus 9660

Docusaurus ist eine Single Page Application (= Die HTML Seite wird nur einmal geladen. Alle weiteren Inhalte werden dynamisch hinzugefügt), die von dem Open Source Zweig von Facebook entwickelt wird. Docusaurus wird, wie der Name schon andeutet, für online Dokumentationen genutzt, kann jedoch beliebig erweitert werden. Die Grundlage der App ist das REACT Framework.

Daten laden (Fetch, Axios, …)

Docusaurus ist eine Single Page Application, doch kann man mit Hilfe von AJAX (Asynchronous JavaScript And XML) asynchron Daten z.B.: von einer Datenbank abfragen.

Mittels des „useEffect“ Hooks und dem React State, können Elemente verändert und automatisch aktualisiert werden, wenn der AJAX Request abgeschlossen ist.

Als Beispiel dient ein einfaches Login System, welches mittels PHP Dateien eine Session für den Nutzer erstellt und diese abfragt.

Dafür habe ich mehrere React Components erstellt:

  • Session.js – prüft, ob es eine aktuelle Session gibt. Wenn ja dann wird Logout.js angezeigt, sonst Login.js
  • Login.js – ein Login Formular, in dem der Nutzer seine Daten eingeben kann, um eine neue Session zu erstellen.
  • Logout.js – ein Logout Button wird angezeigt, der den Nutzer abmeldet, also die Session zerstört.

Die Components nutzen den weiter unten beschriebenen globalen Context, um sich automatisch zu aktualisieren, wenn Werte sich ändern.

Session.js

import React, { useContext } from "react";
import axios from "axios";
import Login from "./Login";
import Logout from "./Logout";
import { MyContext } from "./MyContext";

export default function Session() {
  const [myValues, setMyValues] = useContext(MyContext);
  const urlSession = "https://test.sqlverine.org/php/session.php";

  React.useEffect(() => {
    axios.get(urlSession).then((response) => {
      if (response.data == 1) {
        setMyValues((oldValues) => ({ ...oldValues, loggedIn: true }));
      }
    });
  }, []);

  return (
    <div>
      <div>{myValues.loggedIn ? <Logout /> : <Login />}</div>
    </div>
  );
}

Login.js

import React, { useContext, useState } from "react";
import { MyContext } from "./MyContext";
import axios from "axios";
import Alert from "./Alert";

export default function Login() {
  const [myValues, setMyValues] = useContext(MyContext);
  const urlSession = "https://test.sqlverine.org/php/session.php";
  const urlLogin = "https://test.sqlverine.org/php/login.php";
  const [name, setName] = useState("");
  const [password, setPassword] = useState("");
  const [alert, setAlert] = useState("");

  // Login
  async function handleLogin(event) {
    axios
      .post(urlLogin, {
        name: name,
        password: password,
      })
      .then(function (response) {
        if (response.data == 1) {
          setMyValues((oldValues) => ({ ...oldValues, loggedIn: true }));
        }else{
          setAlert(<Alert alert="Benutzername oder Password sind nicht korrekt!" />);          
        }
      })
      .catch(function (error) {
        console.log(error);
        setAlert(<Alert alert={error.toString()} />);
      });
  }

  // check Session
  async function handleSession(event) {
    axios.get(urlSession).then((response) => {
      console.log(response.data);
    });
  }

  return (
    <div>
      <div className="row">
        <div className="col">
          <p>Benutzername:</p>
        </div>
        <div className="col">
          <input
            type="text"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
        </div>
      </div>
      <div className="row">
        <div className="col">
          <p> Passwort:</p>
        </div>
        <div className="col">
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
        </div>
      </div>
      <div>
        {alert}
      </div>
      <div className="row">
        <div className="col">
          <button className="button button--success" onClick={handleLogin}>
            Login
          </button>
          <button className="button button--info  margin-left--xs" onClick={handleSession}>
            Session
          </button>
        </div>
      </div>
    </div>
  );
}

Logout.js

import React, { useContext } from "react";
import axios from "axios";
import { MyContext } from "./MyContext";

export default function Logout() {
  const urlLogout = "https://test.sqlverine.org/php/logout.php";
  const [myValues, setMyValues] = useContext(MyContext);

  // Login
  async function handleLogout(event) {
    axios.get(urlLogout).then((response) => {
      setMyValues((oldValues) => ({ ...oldValues, loggedIn: false }));
    });
  }

  return <button class="button button--danger" onClick={() => handleLogout()}>Logout</button>;
}

Globaler Context

Der Vorteil von React und Single Page Applications ist, dass man einen Context / einen Store nutzen kann, der Daten global für die ganze App zur Verfügung stellen kann.

Im folgenden Beispiel wird ein globaler Context erstellt, der dann von jedem Component/von jeder Seite genutzt werden kann.

1) Context erstellen

Zuerst erstellen wir eine „MyContext.js„. Hier wird ein Context erstellt und dieser wird exportiert, sodass er in andere JS Dateien genutzt werden kann. Des Weiteren wird ein ContextProvider erstellt und diesem ein Objekt mit verschiedenen Werten übergeben.

import React, {useState} from "react";

const MyContext = React.createContext({});

function MyContextProvider(props) {
  const [myValues, setMyValues] = useState({
    counter: 0,
    user: "Richi",
    loggedIn: false,
  });

  return (
    <MyContext.Provider value={[myValues, setMyValues]}>
      {props.children}
    </MyContext.Provider>
  );
}

export { MyContext, MyContextProvider };

2) Context global im Docusaurus bereitstellen

Um einen Context für alle Elemente der Single Page Application nutzen zu können, muss dieser über einen Context Provider an alle Children übergeben werden. Im Docusaurus kann man alle Elemente in einer Root.js Datei abfangen und den Context hinzufügen.

Dazu erstellt man im „src“ Ordner einen Order mit dem Namen „theme“ und dort eine JS Datei „Root.js„. Hier wird der ContextProvider geladen, um die Contextwerte allen Elementen zur Verfügung zu stellen:

import React, { useState } from "react";
import { MyContextProvider } from "../components/MyContext";

// Default implementation, that you can customize
function Root({ children }) {
  return (
    <MyContextProvider>
      <>{children}</>
    </MyContextProvider>
  );
}
export default Root;

Der Provider umschließt die Variable „children“, die alle Elemente des Docusaurus beinhaltet. Dadurch steht der Context allen Elementen zur Verfügung.

3) Context Variablen anzeigen

Nun können wir die Variablen in einem neuen Component irgendwo in Docusaurus anzeigen. Dazu habe ich einen Component „TestCounter.js“ erstellt.

import React, { useContext } from "react";
import { MyContext } from "./MyContext";


export default function TestCounter(){

  const [myValues] = useContext(MyContext);

  return(
        <h1>{myValues.counter} and {myValues.user}</h1>
    )
}

4) Context Variablen ändern

Die Attribute des Objekts können wir mit Hilfe von „setMyValues“ verändern, indem wir die Daten des alten Objekts kopieren und den zu ändernden Wert anpassen. Hierfür erstellen wir einen zweiten Component „TestButton.js„.

import React, { useContext } from "react";
import { MyContext } from "./MyContext";

export default function TestContext(){

    const [myValues, setMyValues] = useContext(MyContext);

    return(
        <button onClick={() => setMyValues(oldValues => ({...oldValues, counter: oldValues.counter +1 }))}> 
            Increment
        </button>
    )
}

Das Kopieren und ändern eines Wertes findet im onClick Event des Buttons statt.

unsere-schule.org

×

Docuaurus

Code: 9660