Erstellen einer React-App, die AEM GraphQL-APIs verwendet

In diesem Kapitel erfahren Sie, wie AEM GraphQL-APIs das Erlebnis in einer externen Anwendung fördern können.

Eine einfache React-App wird zum Abfragen und Anzeigen verwendet Team und Person Inhalte, die von AEM GraphQL-APIs bereitgestellt werden. Die Verwendung von React ist größtenteils unwichtig, und die verbrauchende externe Anwendung könnte in jedem Rahmen für jede Plattform geschrieben werden.

Voraussetzungen

Es wird davon ausgegangen, dass die in den vorherigen Teilen dieses mehrteiligen Tutorials beschriebenen Schritte abgeschlossen wurden, oder tutorial-solution-content.zip wird auf Ihrem AEM as a Cloud Service Autoren- und Veröffentlichungsdienst installiert.

IDE-Screenshots in diesem Kapitel stammen von Visual Studio-Code

Die folgende Software muss installiert sein:

Ziele

Erfahren Sie mehr über:

  • Herunterladen und Starten der React-Beispielanwendung
  • Abfragen AEM GraphQL-Endpunkte mit der AEM Headless JS SDK
  • AEM für eine Liste von Teams und deren referenzierte Mitglieder abfragen
  • Abfrage AEM Details eines Teammitglieds

Beispiel-React-App abrufen

In diesem Kapitel wird eine ausgeschaltete React-Beispielanwendung implementiert, die den Code enthält, der für die Interaktion mit AEM GraphQL-API erforderlich ist, und Teams- und Personendaten anzeigt, die von ihnen erhalten wurden.

Der Beispiel-Quell-Code der React-App ist auf Github.com unter https://github.com/adobe/aem-guides-wknd-graphql/tree/main/basic-tutorial

So rufen Sie die React-App ab:

  1. Klonen Sie die WKND GraphQL React-Beispielanwendung aus Github.com.

    $ cd ~/Code
    $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
    
  2. Navigieren Sie zu basic-tutorial und öffnen Sie sie in Ihrer IDE.

    $ cd ~/Code/aem-guides-wknd-graphql/basic-tutorial
    $ code .
    

    React-App in VSCode

  3. Aktualisieren .env.development , um eine Verbindung zum as a Cloud Service Veröffentlichungsdienst AEM.

    • Satz REACT_APP_HOST_URIDer Wert von ist die Veröffentlichungs-URL Ihres AEM as a Cloud Service (z. B. REACT_APP_HOST_URI=https://publish-p123-e456.adobeaemcloud.com) und REACT_APP_AUTH_METHODWert von none
    HINWEIS

    Vergewissern Sie sich, dass Sie die Projektkonfiguration, Inhaltsfragmentmodelle, erstellten Inhaltsfragmente, GraphQL-Endpunkte und persistente Abfragen aus vorherigen Schritten veröffentlicht haben.

    Wenn Sie die oben genannten Schritte für das lokale AEM Author-SDK ausgeführt haben, können Sie auf http://localhost:4502 und REACT_APP_AUTH_METHODWert von basic.

  4. Wechseln Sie in der Befehlszeile zum aem-guides-wknd-graphql/basic-tutorial Ordner

  5. React-App starten

    $ cd ~/Code/aem-guides-wknd-graphql/basic-tutorial
    $ npm install
    $ npm start
    
  6. Die React-App startet im Entwicklungsmodus auf http://localhost:3000/. Änderungen, die während des Tutorials an der React-App vorgenommen wurden, werden sofort übernommen.

Teilweise implementierte React-App

WICHTIG

Dies ist eine teilweise implementierte React-App, die nach den Schritten abgeschlossen ist. Für die JavaScript-Dateien, für die Implementierungsarbeiten erforderlich sind, gibt es den folgenden Kommentar: Stellen Sie sicher, dass Sie den Code in diesen Dateien mit dem in diesem Tutorial angegebenen Code hinzufügen/aktualisieren.

//​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​***

// TODO : Implementieren Sie dies, indem Sie die Schritte aus AEM Headless-Tutorial befolgen.

//​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​**​***

Anatomie der React-App

Die React-Beispielanwendung besteht aus drei Hauptteilen:

  1. Die src/api enthält Dateien, die zum Erstellen von GraphQL-Abfragen für AEM verwendet werden.

    • src/api/aemHeadlessClient.js initialisiert und exportiert den AEM Headless-Client, der zur Kommunikation mit AEM verwendet wird
    • src/api/usePersistedQueries.js implementiert benutzerdefinierte React-Hooks Daten aus AEM GraphQL an die Teams.js und Person.js Komponenten anzeigen.
  2. Die src/components/Teams.js zeigt mithilfe einer Listenabfrage eine Liste der Teams und ihrer Mitglieder an.

  3. Die src/components/Person.js zeigt die Details einer einzelnen Person mithilfe einer parametrisierten Abfrage mit einem Ergebnis an.

Überprüfen des AEMHeadless-Objekts

Überprüfen Sie die aemHeadlessClient.js -Datei für die Erstellung der AEMHeadless -Objekt, das zur Kommunikation mit AEM verwendet wird.

  1. Öffnen Sie src/api/aemHeadlessClient.js.

  2. Überprüfen Sie die Zeilen 1-40:

    • Der Import AEMHeadless Erklärung AEM Headless-Client für JavaScript, Zeile 11.

    • Die Konfiguration der Autorisierung basierend auf Variablen, die in .env.development, Zeile 14-22 und dem Ausdruck für die Pfeilfunktion setAuthorization, Zeile 31-40.

    • Die serviceUrl -Setup für die enthaltene Entwicklungs-Proxy Konfiguration, Zeile 27.

  3. Die Zeilen 42-49 sind am wichtigsten, da sie die AEMHeadless und exportieren Sie es zur Verwendung in der gesamten React-App.

// Initialize the AEM Headless Client and export it for other files to use
const aemHeadlessClient = new AEMHeadless({
  serviceURL: serviceURL,
  endpoint: REACT_APP_GRAPHQL_ENDPOINT,
  auth: setAuthorization(),
});

export default aemHeadlessClient;

Implementieren, um AEM von GraphQL persistente Abfragen auszuführen

Öffnen Sie die usePersistedQueries.js -Datei, um die generische fetchPersistedQuery(..) -Funktion zum Ausführen der AEM von GraphQL-gespeicherten Abfragen. Die fetchPersistedQuery(..) -Funktion verwendet die aemHeadlessClient -Objekt runPersistedQuery() -Funktion, um Abfragen asynchron und versprechen-basiertes Verhalten auszuführen.

Später, benutzerdefinierte React useEffect hook ruft diese Funktion auf, um bestimmte Daten aus AEM abzurufen.

  1. In src/api/usePersistedQueries.js update fetchPersistedQuery(..), Zeile 35 mit dem folgenden Code.
/**
 * Private, shared function that invokes the AEM Headless client.
 *
 * @param {String} persistedQueryName the fully qualified name of the persisted query
 * @param {*} queryParameters an optional JavaScript object containing query parameters
 * @returns the GraphQL data or an error message
 */
async function fetchPersistedQuery(persistedQueryName, queryParameters) {
  let data;
  let err;

  try {
    // AEM GraphQL queries are asynchronous, either await their return or use Promise-based syntax
    const response = await aemHeadlessClient.runPersistedQuery(
      persistedQueryName,
      queryParameters
    );
    // The GraphQL data is stored on the response's data field
    data = response?.data;
  } catch (e) {
    // An error occurred, return the error messages
    err = e
      .toJSON()
      ?.map((error) => error.message)
      ?.join(", ");
    console.error(e.toJSON());
  }

  // Return the GraphQL and any errors
  return { data, err };
}

Implementieren der Funktionen von Teams

Erstellen Sie als Nächstes die Funktion zum Anzeigen der Teams und ihrer Mitglieder in der Hauptansicht der React-App. Diese Funktion erfordert:

  • Eine neue Benutzerdefinierter React-useEffect-Erweiterungspunkt in src/api/usePersistedQueries.js , das die my-project/all-teams persistente Abfrage, die eine Liste von Team-Inhaltsfragmenten in AEM zurückgibt.
  • Eine React-Komponente unter src/components/Teams.js , das den neuen benutzerdefinierten React aufruft useEffect Erweitern und rendert die Team-Daten.

Nach Abschluss des Vorgangs werden in der Hauptansicht der App die Teamdaten aus AEM angezeigt.

Team-Ansicht

Schritte

  1. Öffnen Sie src/api/usePersistedQueries.js.

  2. Suchen Sie die Funktion useAllTeams()

  3. So erstellen Sie eine useEffect Erweiterungspunkt, der die persistente Abfrage aufruft my-project/all-teams via fetchPersistedQuery(..), fügen Sie den folgenden Code hinzu. Der Erweiterungspunkt gibt auch nur die relevanten Daten aus der AEM GraphQL-Antwort zurück unter data?.teamList?.items, sodass die React-Ansicht-Komponenten unabhängig von den übergeordneten JSON-Strukturen sein können.

    /**
     * Custom hook that calls the 'my-project/all-teams' persisted query.
     *
     * @returns an array of Team JSON objects, and array of errors
     */
    export function useAllTeams() {
      const [teams, setTeams] = useState(null);
      const [error, setError] = useState(null);
    
      // Use React useEffect to manage state changes
      useEffect(() => {
        async function fetchData() {
          // Call the AEM GraphQL persisted query named "my-project/all-teams"
          const { data, err } = await fetchPersistedQuery(
            "my-project/all-teams"
          );
          // Sets the teams variable to the list of team JSON objects
          setTeams(data?.teamList?.items);
          // Set any errors
          setError(err);
        }
        // Call the internal fetchData() as per React best practices
        fetchData();
      }, []);
    
      // Returns the teams and errors
      return { teams, error };
    }
    
  4. Öffnen Sie src/components/Teams.js

  5. Im Teams React-Komponente: Rufen Sie die Liste der Teams aus AEM mithilfe der useAllTeams() Haken.

    import { useAllTeams } from "../api/usePersistedQueries";
    ...
    function Teams() {
      // Get the Teams data from AEM using the useAllTeams
      const { teams, error } = useAllTeams();
      ...
    }
    
  6. Führen Sie die ansichtsbasierte Datenvalidierung durch, zeigen Sie eine Fehlermeldung an oder laden Sie die Anzeige basierend auf den zurückgegebenen Daten.

    function Teams() {
      const { teams, error } = useAllTeams();
    
      // Handle error and loading conditions
      if (error) {
        // If an error ocurred while executing the GraphQL query, display an error message
        return <Error errorMessage={error} />;
      } else if (!teams) {
        // While the GraphQL request is executing, show the Loading indicator
        return <Loading />;
      }
      ...
    }
    
  7. Rendern Sie schließlich die Team-Daten. Jedes von der GraphQL-Abfrage zurückgegebene Team wird mithilfe der bereitgestellten Team React-Unterkomponente.

    import React from "react";
    import { Link } from "react-router-dom";
    import { useAllTeams } from "../api/usePersistedQueries";
    import Error from "./Error";
    import Loading from "./Loading";
    import "./Teams.scss";
    
    function Teams() {
      const { teams, error } = useAllTeams();
    
      // Handle error and loading conditions
      if (error) {
        return <Error errorMessage={error} />;
      } else if (!teams) {
        return <Loading />;
      }
    
      // Teams have been populated by AEM GraphQL query. Display the teams.
      return (
        <div className="teams">
          {teams.map((team, index) => {
            return <Team key={index} {...team} />;
          })}
        </div>
      );
    }
    
    // Render single Team
    function Team({ title, shortName, description, teamMembers }) {
      // Must have title, shortName and at least 1 team member
      if (!title || !shortName || !teamMembers) {
        return null;
      }
    
      return (
        <div className="team">
          <h2 className="team__title">{title}</h2>
          <p className="team__description">{description.plaintext}</p>
          <div>
            <h4 className="team__members-title">Members</h4>
            <ul className="team__members">
              {/* Render the referenced Person models associated with the team */}
              {teamMembers.map((teamMember, index) => {
                return (
                  <li key={index} className="team__member">
                    <Link to={`/person/${teamMember.fullName}`}>
                      {teamMember.fullName}
                    </Link>
                  </li>
                );
              })}
            </ul>
          </div>
        </div>
      );
    }
    
    export default Teams;
    

Funktion "Person implementieren"

Mit dem Team-Funktionen abschließen, lassen Sie uns die Funktion implementieren, um die Anzeige in den Details eines Teammitglieds oder einer Person zu verarbeiten.

Diese Funktion erfordert:

  • Eine neue Benutzerdefinierter React-useEffect-Erweiterungspunkt in src/api/usePersistedQueries.js , der die parametrisierte my-project/person-by-name persistente Abfrage und gibt einen Datensatz für eine einzelne Person zurück.

  • Eine React-Komponente unter src/components/Person.js , der den vollständigen Namen einer Person als Abfrageparameter verwendet, ruft die neue benutzerdefinierte React auf useEffect Erweitern und rendert die Personendaten.

Wenn Sie nach Abschluss des Vorgangs den Namen einer Person in der Ansicht "Teams"auswählen, wird die Personenansicht angezeigt.

Person

  1. Öffnen Sie src/api/usePersistedQueries.js.

  2. Suchen Sie die Funktion usePersonByName(fullName)

  3. So erstellen Sie eine useEffect Erweiterungspunkt, der die persistente Abfrage aufruft my-project/all-teams via fetchPersistedQuery(..), fügen Sie den folgenden Code hinzu. Der Erweiterungspunkt gibt auch nur die relevanten Daten aus der AEM GraphQL-Antwort zurück unter data?.teamList?.items, sodass die React-Ansicht-Komponenten unabhängig von den übergeordneten JSON-Strukturen sein können.

    /**
     * Calls the 'my-project/person-by-name' and provided the {fullName} as the persisted query's `name` parameter.
     *
     * @param {String!} fullName the full
     * @returns a JSON object representing the person
     */
    export function usePersonByName(fullName) {
      const [person, setPerson] = useState(null);
      const [errors, setErrors] = useState(null);
    
      useEffect(() => {
        async function fetchData() {
          // The key is the variable name as defined in the persisted query, and may not match the model's field name
          const queryParameters = { name: fullName };
    
          // Invoke the persisted query, and pass in the queryParameters object as the 2nd parameter
          const { data, err } = await fetchPersistedQuery(
            "my-project/person-by-name",
            queryParameters
          );
    
          if (err) {
            // Capture errors from the HTTP request
            setErrors(err);
          } else if (data?.personList?.items?.length === 1) {
            // Set the person data after data validation
            setPerson(data.personList.items[0]);
          } else {
            // Set an error if no person could be found
            setErrors(`Cannot find person with name: ${fullName}`);
          }
        }
        fetchData();
      }, [fullName]);
    
      return { person, errors };
    }
    
  4. Öffnen Sie src/components/Person.js

  5. Im Person React-Komponente, analysieren Sie die fullName Route-Parameter und rufen Sie die Personendaten mithilfe der AEM ab. usePersonByName(fullName) Haken.

    import { useParams } from "react-router-dom";
    import { usePersonByName } from "../api/usePersistedQueries";
    ...
    function Person() {
      // Read the person's `fullName` which is the parameter used to query for the person's details
      const { fullName } = useParams();
    
      // Query AEM for the Person's details, using the `fullName` as the filtering parameter
      const { person, error } = usePersonByName(fullName);
      ...
    }
    
  6. Führen Sie eine ansichtsbasierte Datenvalidierung durch, zeigen Sie eine Fehlermeldung an oder laden Sie einen Indikator basierend auf den zurückgegebenen Daten.

    function Person() {
      // Read the person's `fullName` which is the parameter used to query for the person's details
      const { fullName } = useParams();
    
      // Query AEM for the Person's details, using the `fullName` as the filtering parameter
      const { person, error } = usePersonByName(fullName);
    
      // Handle error and loading conditions
      if (error) {
        return <Error errorMessage={error} />;
      } else if (!person) {
        return <Loading />;
      }
      ...
    }
    
  7. Geben Sie schließlich die Personendaten wieder.

    import React from "react";
    import { useParams } from "react-router-dom";
    import { usePersonByName } from "../api/usePersistedQueries";
    import { mapJsonRichText } from "../utils/renderRichText";
    import Error from "./Error";
    import Loading from "./Loading";
    import "./Person.scss";
    
    function Person() {
      // Read the person's `fullName` which is the parameter used to query for the person's details
      const { fullName } = useParams();
    
      // Query AEM for the Person's details, using the `fullName` as the filtering parameter
      const { person, error } = usePersonByName(fullName);
    
      // Handle error and loading conditions
      if (error) {
        return <Error errorMessage={error} />;
      } else if (!person) {
        return <Loading />;
      }
    
      // Render the person data
      return (
        <div className="person">
          <img
            className="person__image"
            src={process.env.REACT_APP_HOST_URI+person.profilePicture._path}
            alt={person.fullName}
          />
          <div className="person__occupations">
            {person.occupation.map((occupation, index) => {
              return (
                <span key={index} className="person__occupation">
                  {occupation}
                </span>
              );
            })}
          </div>
          <div className="person__content">
            <h1 className="person__full-name">{person.fullName}</h1>
            <div className="person__biography">
              {/* Use this utility to transform multi-line text JSON into HTML */}
              {mapJsonRichText(person.biographyText.json)}
            </div>
          </div>
        </div>
      );
    }
    
    export default Person;
    

Testen der App

Überprüfen der App http://localhost:3000/ und klicken Sie auf Mitglieder Links. Außerdem können Sie dem Team-Alpha weitere Teams und/oder Mitglieder hinzufügen, indem Sie Inhaltsfragmente in AEM hinzufügen.

Unterhalb des

Öffnen Sie die Entwicklertools > Netzwerk und Filter für all-teams -Anfrage, beachten Sie die GraphQL-API-Anfrage /graphql/execute.json/my-project/all-teams gegen http://localhost:3000 und NOT gegen den Wert von REACT_APP_HOST_URI(z. B. https://publish-p123-e456.adobeaemcloud.com), da dies Proxy-Einrichtung using http-proxy-middleware -Modul.

GraphQL-API-Anfrage über Proxy

Überprüfen Sie die wichtigsten ../setupProxy.js Datei und innerhalb ../proxy/setupProxy.auth.**.js -Dateien erkennen, wie /content und /graphql Pfade werden proximiert und weisen darauf hin, dass es sich nicht um ein statisches Asset handelt.

module.exports = function(app) {
  app.use(
    ['/content', '/graphql'],
  ...

Dies ist jedoch keine geeignete Option für die Produktionsbereitstellung und weitere Details finden Sie unter Produktionsbereitstellung Abschnitt.

Herzlichen Glückwunsch!

Herzlichen Glückwunsch! Sie haben die React-App erfolgreich erstellt, um Daten aus AEM GraphQL-APIs als Teil des grundlegenden Tutorials zu nutzen und anzuzeigen!

Auf dieser Seite