Een React-app ontwikkelen die AEM GraphQL API's gebruikt
In dit hoofdstuk verkent u hoe AEM GraphQL API's de ervaring in een externe toepassing kunnen aansturen.
Een eenvoudige React app wordt gebruikt om Team en Persoon inhoud te vragen en te tonen die door GraphQL APIs wordt blootgesteld te AEM. Het gebruik van React is grotendeels onbelangrijk, en de verbruikende externe toepassing zou in om het even welk kader voor om het even welk platform kunnen worden geschreven.
Vereisten
Men veronderstelt dat de stappen die in de vorige delen van dit meerdelige leerprogramma worden geschetst zijn voltooid, of basis-tutorial-solution.content.zipis geïnstalleerd op uw Auteur van AEM as a Cloud Service en de diensten van Publish.
winde screenshots in dit hoofdstuk komen uit Code van Visual Studio
De volgende software moet worden geïnstalleerd:
Doelstellingen
Leer hoe u:
- De voorbeeldtoepassing React downloaden en starten
- De vraag AEM GraphQL eindpunten gebruikend AEM Zwaarloze JS SDK
- De AEM van de vraag voor een lijst van teams, en hun referenced leden
- De AEM van de vraag voor de details van een teamlid
De voorbeeldtoepassing React ophalen
In dit hoofdstuk wordt een uitgelijnde voorbeeldtoepassing React geïmplementeerd met de code die vereist is voor interactie met AEM GraphQL API en de gegevens van het weergaveteam en de persoon die van hen zijn verkregen.
De voorbeeldbroncode van de React-app is beschikbaar op Github.com op https://github.com/adobe/aem-guides-wknd-graphql/tree/main/basic-tutorial
Zo krijgt u de React-app:
-
Kloon de steekproefWKND GraphQL React app van Github.com.
code language-shell $ cd ~/Code $ git clone git@github.com:adobe/aem-guides-wknd-graphql.git
-
Navigeer naar de map
basic-tutorial
en open deze in uw IDE.code language-shell $ cd ~/Code/aem-guides-wknd-graphql/basic-tutorial $ code .
-
Werk
.env.development
bij om verbinding te maken met de AEM as a Cloud Service Publish-service.- Stel de waarde van
REACT_APP_HOST_URI
in op de AEM as a Cloud Service Publish-URL (bijvoorbeeldREACT_APP_HOST_URI=https://publish-p123-e456.adobeaemcloud.com
) enREACT_APP_AUTH_METHOD
''s value tonone
note note NOTE Zorg ervoor u projectconfiguratie, de modellen van het Fragment van de Inhoud, authored de Fragmenten van de Inhoud, GraphQL eindpunten en voortgeduurde vragen van vorige stappen hebt gepubliceerd. Als u bovenstaande stappen hebt uitgevoerd op de lokale AEM Auteur-SDK, kunt u naar http://localhost:4502
en de waarde vanREACT_APP_AUTH_METHOD
naarbasic
verwijzen. - Stel de waarde van
-
Ga vanaf de opdrachtregel naar de map
aem-guides-wknd-graphql/basic-tutorial
-
De React-app starten
code language-shell $ cd ~/Code/aem-guides-wknd-graphql/basic-tutorial $ npm install $ npm start
-
React app begint op ontwikkelingswijze op http://localhost:3000/. Wijzigingen die tijdens de zelfstudie in de React-app worden aangebracht, worden direct doorgevoerd.
Anatomie van de React-app
De voorbeeldtoepassing React bestaat uit drie hoofdonderdelen:
-
De map
src/api
bevat bestanden die worden gebruikt om GraphQL-query's naar AEM te maken.src/api/aemHeadlessClient.js
initialiseert en exporteert de AEM Headless-client die wordt gebruikt voor communicatie met AEMsrc/api/usePersistedQueries.js
voert douane React haksterugkeergegevens van AEM GraphQL aanTeams.js
enPerson.js
meningscomponenten uit.
-
Het
src/components/Teams.js
dossier toont een lijst van teams en hun leden, door een lijstvraag te gebruiken. -
In het bestand
src/components/Person.js
worden de details van één persoon weergegeven, waarbij een query met één resultaat als parameter wordt gebruikt.
Het object AEMHeadless controleren
Bekijk het aemHeadlessClient.js
-bestand voor informatie over het maken van het AEMHeadless
-object dat wordt gebruikt om te communiceren met AEM.
-
Open
src/api/aemHeadlessClient.js
. -
Herzie de lijnen 1-40:
-
De invoer
AEMHeadless
verklaring van de AEM Cliënt zonder kop voor JavaScript, lijn 11. -
De configuratie van de autorisatie op basis van de variabelen in
.env.development
, regel 14-22 en, de expressie van de pijlfunctiesetAuthorization
, regel 31-40. -
De
serviceUrl
opstelling voor de inbegrepen configuratie van de ontwikkelingsvolmacht, lijn 27.
-
-
De regels 42-49 zijn het belangrijkst, aangezien zij de
AEMHeadless
cliënt concretiseren en het voor gebruik door React app uitvoeren.
// 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;
Implementeren om AEM GraphQL doorlopende query's uit te voeren
Als u de algemene functie fetchPersistedQuery(..)
wilt implementeren om de AEM GraphQL-query's die u hebt uitgevoerd, uit te voeren, opent u het usePersistedQueries.js
-bestand. De functie fetchPersistedQuery(..)
gebruikt de functie aemHeadlessClient
object runPersistedQuery()
om query asynchroon, op belofte gebaseerd gedrag uit te voeren.
Later wordt deze functie aangeroepen door de aangepaste React useEffect
-haak om specifieke gegevens van AEM op te halen.
- In
src/api/usePersistedQueries.js
updatefetchPersistedQuery(..)
, lijn 35, met de hieronder 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 };
}
Teams implementeren
Vervolgens ontwikkelt u de functionaliteit om de Teams en hun leden weer te geven in de hoofdweergave van de React-app. Deze functionaliteit vereist:
- Een nieuwe haak React useEffectin
src/api/usePersistedQueries.js
diemy-project/all-teams
voortgeduurde vraag aanhaalt, die een lijst van de Fragmenten van de Inhoud van het Team in AEM terugkeert. - Een React component bij
src/components/Teams.js
die de nieuwe aangepaste ReactuseEffect
haak aanhaalt, en de teamgegevens rendert.
Als de hoofdweergave van de app is voltooid, worden de teamgegevens uit AEM ingevuld.
Stappen
-
Open
src/api/usePersistedQueries.js
. -
De functie zoeken
useAllTeams()
-
Voeg de volgende code toe om een
useEffect
-haak te maken die de voortgezette querymy-project/all-teams
viafetchPersistedQuery(..)
aanroept. De haak retourneert ook alleen de relevante gegevens van de AEM GraphQL-respons opdata?.teamList?.items
, zodat de React-weergavecomponenten zich niet bewust zijn van de bovenliggende JSON-structuren.code language-javascript /** * 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 }; }
-
Openen
src/components/Teams.js
-
Haal in de component
Teams
React de lijst met teams op van AEM met deuseAllTeams()
-haak.code language-javascript import { useAllTeams } from "../api/usePersistedQueries"; ... function Teams() { // Get the Teams data from AEM using the useAllTeams const { teams, error } = useAllTeams(); ... }
-
Voer de op weergave gebaseerde gegevensvalidatie uit en geef een foutbericht of ladingsindicator weer op basis van de geretourneerde gegevens.
code language-javascript 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 />; } ... }
-
Tot slot geef de teamgegevens terug. Elk team dat door de GraphQL-query wordt geretourneerd, wordt gerenderd met de meegeleverde subcomponent
Team
React.code language-javascript 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;
Functie Personen implementeren
Met de functionaliteit van Teamsvolledig, voeren wij de functionaliteit uit om de vertoning op de details van een teamlid, of persoon te behandelen.
Deze functionaliteit vereist:
-
Een nieuwe haak React useEffectin
src/api/usePersistedQueries.js
die de geparameterizedmy-project/person-by-name
voortgeduurde vraag aanhaalt, en één enkel persoonverslag terugkeert. -
Een component React bij
src/components/Person.js
die de volledige naam van een persoon als vraagparameter gebruikt, haalt de nieuwe douane ReactuseEffect
haak aan, en geeft de persoongegevens terug.
Als u de naam van een persoon hebt geselecteerd in de weergave Teams, wordt de weergave van die persoon weergegeven.
-
Open
src/api/usePersistedQueries.js
. -
De functie zoeken
usePersonByName(fullName)
-
Voeg de volgende code toe om een
useEffect
-haak te maken die de voortgezette querymy-project/all-teams
viafetchPersistedQuery(..)
aanroept. De haak retourneert ook alleen de relevante gegevens van de AEM GraphQL-respons opdata?.teamList?.items
, zodat de React-weergavecomponenten zich niet bewust zijn van de bovenliggende JSON-structuren.code language-javascript /** * 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 }; }
-
Openen
src/components/Person.js
-
In de component
Person
React, ontleedt defullName
routeparameter, en haalt de persoongegevens van AEM gebruikend deusePersonByName(fullName)
haak.code language-javascript 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); ... }
-
Voer op weergave gebaseerde gegevensvalidatie uit en geef een foutbericht of ladingsindicator weer op basis van de geretourneerde gegevens.
code language-javascript 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 />; } ... }
-
Tot slot geef de persoongegevens terug.
code language-javascript 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;
Probeer de app
Herzie app http://localhost:3000/en klik Leden verbindingen. Ook kunt u meer teams en/of leden aan de Alpha van het Team toevoegen door de Fragmenten van de Inhoud in AEM toe te voegen.
Onder de hood
Open browser Hulpmiddelen van de Ontwikkelaar > Netwerk en Filter voor all-teams
verzoek. De GraphQL API-aanvraag /graphql/execute.json/my-project/all-teams
wordt uitgevoerd tegen http://localhost:3000
en NOT tegen de waarde van REACT_APP_HOST_URI
, bijvoorbeeld <https://publish-pxxx-exxx.adobeaemcloud.com
. De verzoeken worden gemaakt tegen het React toepassingsdomein omdat volmachtsopstellinggebruikend http-proxy-middleware
module wordt toegelaten.
Bekijk het hoofd ../setupProxy.js
dossier en binnen ../proxy/setupProxy.auth.**.js
dossiers merken hoe /content
en /graphql
de wegen proxied zijn en erop wijzen het geen statisch middel is.
module.exports = function(app) {
app.use(
['/content', '/graphql'],
...
Het gebruiken van de lokale volmacht is geen geschikte optie voor productieplaatsing en meer details kunnen bij sectie van de Plaatsing van de Productie worden gevonden.
Gefeliciteerd! congratulations
Gefeliciteerd! U hebt de React-app gemaakt om gegevens van AEM GraphQL API's te verbruiken en weer te geven als onderdeel van de basiszelfstudie.