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.
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:
Erfahren Sie mehr über:
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:
Klonen Sie die WKND GraphQL React-Beispielanwendung aus Github.com.
$ cd ~/Code
$ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
Navigieren Sie zu basic-tutorial
und öffnen Sie sie in Ihrer IDE.
$ cd ~/Code/aem-guides-wknd-graphql/basic-tutorial
$ code .
Aktualisieren .env.development
, um eine Verbindung zum as a Cloud Service Veröffentlichungsdienst AEM.
REACT_APP_HOST_URI
Der 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_METHOD
Wert von none
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_METHOD
Wert von basic
.
Wechseln Sie in der Befehlszeile zum aem-guides-wknd-graphql/basic-tutorial
Ordner
React-App starten
$ cd ~/Code/aem-guides-wknd-graphql/basic-tutorial
$ npm install
$ npm start
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.
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.
//***************************************
Die React-Beispielanwendung besteht aus drei Hauptteilen:
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 wirdsrc/api/usePersistedQueries.js
implementiert benutzerdefinierte React-Hooks Daten aus AEM GraphQL an die Teams.js
und Person.js
Komponenten anzeigen.Die src/components/Teams.js
zeigt mithilfe einer Listenabfrage eine Liste der Teams und ihrer Mitglieder an.
Die src/components/Person.js
zeigt die Details einer einzelnen Person mithilfe einer parametrisierten Abfrage mit einem Ergebnis an.
Überprüfen Sie die aemHeadlessClient.js
-Datei für die Erstellung der AEMHeadless
-Objekt, das zur Kommunikation mit AEM verwendet wird.
Öffnen Sie src/api/aemHeadlessClient.js
.
Ü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.
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;
Ö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.
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 };
}
Erstellen Sie als Nächstes die Funktion zum Anzeigen der Teams und ihrer Mitglieder in der Hauptansicht der React-App. Diese Funktion erfordert:
src/api/usePersistedQueries.js
, das die my-project/all-teams
persistente Abfrage, die eine Liste von Team-Inhaltsfragmenten in AEM zurückgibt.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.
Öffnen Sie src/api/usePersistedQueries.js
.
Suchen Sie die Funktion useAllTeams()
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 };
}
Öffnen Sie src/components/Teams.js
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();
...
}
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 />;
}
...
}
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;
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.
Öffnen Sie src/api/usePersistedQueries.js
.
Suchen Sie die Funktion usePersonByName(fullName)
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 };
}
Öffnen Sie src/components/Person.js
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);
...
}
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 />;
}
...
}
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;
Ü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.
Ö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.
Ü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! Sie haben die React-App erfolgreich erstellt, um Daten aus AEM GraphQL-APIs als Teil des grundlegenden Tutorials zu nutzen und anzuzeigen!