Creación de una aplicación de React con las API de entrega de fragmentos de contenido de AEM
En este capítulo, explora cómo la entrega de fragmentos de contenido de AEM con API de OpenAPI puede impulsar la experiencia en aplicaciones externas.
Se usa una aplicación React simple para solicitar y mostrar el contenido de Equipo y Persona expuesto por la entrega de fragmentos de contenido de AEM con las API de OpenAPI. El uso de React no es importante en gran medida, y la aplicación externa utilizada podría escribirse en cualquier marco de trabajo para cualquier plataforma, siempre y cuando pueda realizar solicitudes HTTP a AEM as a Cloud Service.
Requisitos previos
Se da por hecho que se han completado los pasos descritos en las partes anteriores de este tutorial de varias partes.
Se debe instalar el siguiente software:
Objetivos
Obtenga información sobre cómo:
- Descargue e inicie la aplicación React de ejemplo.
- Invoque la entrega de fragmentos de contenido de AEM con las API de OpenAPI para una lista de equipos y sus miembros a los que se hace referencia.
- Invocar la entrega de fragmentos de contenido de AEM con las API de OpenAPI para recuperar los detalles de un miembro del equipo.
Configuración de CORS en AEM as a Cloud Service
Esta aplicación de React de ejemplo se ejecuta localmente (en http://localhost:3000
) y se conecta a la entrega de fragmentos de contenido de AEM del servicio AEM Publish con las API de OpenAPI. Para permitir esta conexión, CORS (Intercambio de recursos de origen cruzado) debe configurarse en el servicio AEM Publish (o Preview).
Proxy CORS local
Como alternativa, para desarrollo, ejecute un proxy CORS local que facilite una conexión compatible con CORS a AEM.
$ npm install --global lcp
$ lcp --proxyUrl https://publish-p<PROGRAM_ID>-e<ENVIRONMENT_ID>.adobeaemcloud.com
Actualice el valor --proxyUrl
a la dirección URL de publicación (o vista previa) de AEM.
Con el proxy CORS local en ejecución, acceda a las API de entrega de fragmentos de contenido de AEM en http://localhost:8010/proxy
para evitar problemas con CORS.
Clonar la aplicación React de ejemplo
Se implementa una aplicación React de ejemplo con el código necesario para interactuar con la entrega de fragmentos de contenido de AEM con las API de OpenAPI y mostrar los datos de equipo y persona obtenidos de ellas.
El código fuente de la aplicación React de ejemplo está disponible en Github.com.
Para obtener la aplicación React:
-
Clona la aplicación WKND OpenAPI React de ejemplo de Github.com desde la etiqueta
headless_open-api_basic
.code language-shell $ cd ~/Code $ git clone git@github.com:adobe/aem-tutorials.git $ cd aem-tutorials $ git fetch --tags $ git tag $ git checkout tags/headless_open-api_basic
-
Vaya a la carpeta
headless/open-api/basic
y ábrala en su IDE.code language-shell $ cd ~/Code/aem-tutorials/headless/open-api/basic $ code .
-
Actualice
.env
para conectarse al servicio Publicación de AEM as a Cloud Service, ya que aquí se publican los fragmentos de contenido. Esto puede indicar servicio de vista previa de AEM si desea probar la aplicación con el servicio de vista previa de AEM (y los fragmentos de contenido se publican allí).code language-none # AEM Publish (or Preview) service that provides Content Fragments REACT_APP_HOST_URI=https://publish-p123-e456.adobeaemcloud.com
Al usar proxy CORS local, establezca
REACT_APP_HOST_URI
enhttp://localhost:8010/proxy
.code language-none # AEM Publish (or Preview) service that provides Content Fragments REACT_APP_HOST_URI=http://localhost:8010/proxy
-
Inicio de la aplicación React
code language-shell $ cd ~/Code/aem-tutorials/headless/open-api/basic $ npm install $ npm start
-
La aplicación React se inicia en modo de desarrollo en http://localhost:3000/. Los cambios realizados en la aplicación React a lo largo del tutorial se reflejan inmediatamente en el explorador web.
> // TODO: Implemente esto siguiendo los pasos de Tutorial de AEM sin encabezado
> // *****************************
Estructura de la aplicación React
La aplicación React de ejemplo tiene tres partes principales que requieren actualización.
- El archivo
.env
contiene la dirección URL del servicio de publicación (o vista previa) de AEM. src/components/Teams.js
muestra una lista de equipos y sus miembros.src/components/Person.js
muestra los detalles de un solo miembro del equipo.
Implementación de funcionalidad de equipos
Genere la funcionalidad para mostrar los equipos y sus miembros en la vista principal de la aplicación React. Esta funcionalidad requiere lo siguiente:
- Un nuevo vínculo personalizado de React useEffect que invoca la API Enumerar todos los fragmentos de contenido mediante una solicitud de captura y, a continuación, obtiene el valor
fullName
de cadateamMember
para su visualización.
Una vez completada, la vista principal de la aplicación se rellena con los datos de equipos de AEM.
-
Abra
src/components/Teams.js
. -
Implemente el componente Teams para recuperar la lista de equipos de la API Enumerar todos los fragmentos de contenido y procesar el contenido de los equipos. Esto se desglosa en los siguientes pasos:
-
Cree un vínculo
useEffect
que invoque la API Enumerar todos los fragmentos de contenido de AEM y almacene los datos en el estado del componente React. -
Para cada fragmento de contenido Equipo devuelto, invoque la API Obtener un fragmento de contenido para obtener los detalles totalmente hidratados del equipo, incluidos sus miembros y sus
fullNames
. -
Procesar los datos de los equipos mediante la función
Team
.code language-javascript import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import "./Teams.scss"; function Teams() { // The teams folder is the only folder-tree that is allowed to contain Team Content Fragments. const TEAMS_FOLDER = '/content/dam/my-project/en/teams'; // State to store the teams data const [teams, setTeams] = useState(null); useEffect(() => { /** * Fetches all teams and their associated member details * This is a two-step process: * 1. First, get all team content fragments from the specified folder * 2. Then, for each team, fetch the full details including hydrated references to get the team member names */ const fetchData = async () => { try { // Step 1: Fetch all teams from the teams folder const response = await fetch( `${process.env.REACT_APP_HOST_URI}/adobe/contentFragments?path=${TEAMS_FOLDER}` ); const allTeams = (await response.json()).items || []; // Step 2: Fetch detailed information for each team with hydrated references const hydratedTeams = []; for (const team of allTeams) { const hydratedTeamResponse = await fetch( `${process.env.REACT_APP_HOST_URI}/adobe/contentFragments/${team.id}?references=direct-hydrated` ); hydratedTeams.push(await hydratedTeamResponse.json()); } setTeams(hydratedTeams); } catch (error) { console.error("Error fetching content fragments:", error); } }; fetchData(); }, [TEAMS_FOLDER]); // Show loading state while teams data is being fetched if (!teams) { return <div>Loading teams...</div>; } // Render the teams return ( <div className="teams"> {teams.map((team, index) => { return ( <Team key={index} {..team} /> ); })} </div> ); } /** * Team component - renders a single team with its details and members * @param {string} fields - The authorable fields * @param {Object} references - Hydrated references containing member details such as fullName */ function Team({ fields, references, path }) { if (!fields.title || !fields.teamMembers) { return null; } return ( <div className="team"> <h2 className="team__title">{fields.title}</h2> {/* Render description as HTML using dangerouslySetInnerHTML */} <p className="team__description" dangerouslySetInnerHTML={{ __html: fields.description.value }} /> <div> <h4 className="team__members-title">Members</h4> <ul className="team__members"> {/* Render each team member as a link to their detail page */} {fields.teamMembers.map((teamMember, index) => { return ( <li key={index} className="team__member"> <Link to={`/person/${teamMember}`}> {/* Display the full name from the hydrated reference */} {references[teamMember].value.fields.fullName} </Link> </li> ); })} </ul> </div> </div> ); } export default Teams;
Implementar la funcionalidad de persona
Una vez completada la funcionalidad Equipos, implemente la funcionalidad para administrar la visualización de los detalles de un miembro del equipo o de una persona.
Para ello, haga lo siguiente:
-
Abrir
src/components/Person.js
-
En el componente React
Person
, analice el parámetro de rutaid
. Tenga en cuenta que las rutas de la aplicación React se configuraron anteriormente para aceptar el parámetro de URLid
(consulte/src/App.js
). -
Recupere los datos de la persona de AEM mediante la API de obtención de fragmento de contenido.
code language-javascript import "./Person.scss"; import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; /** * Person component - displays detailed information about a single person * Fetches person data from AEM using the ID from the URL parameters */ function Person() { // Get the person ID from the URL parameter const { id } = useParams(); // State to store the person data const [person, setPerson] = useState(null); useEffect(() => { /** * Fetches person data from AEM Content Fragment Delivery API * Uses the ID from URL parameters to get the specific person's details */ const fetchData = async () => { try { /* Hydrate references for access to profilePicture asset path */ const response = await fetch( `${process.env.REACT_APP_HOST_URI}/adobe/contentFragments/${id}?references=direct-hydrated` ); const json = await response.json(); setPerson(json || null); } catch (error) { console.error("Error fetching person data:", error); } }; fetchData(); }, [id]); // Re-fetch when ID changes // Show loading state while person data is being fetched if (!person) { return <div>Loading person...</div>; } return ( <div className="person"> {/* Person profile image - Look up the profilePicture reference in the references object */} <img className="person__image" src={process.env.REACT_APP_HOST_URI + person.references[person.fields.profilePicture].value.path} alt={person.fields.fullName} /> {/* Display person's occupations */} <div className="person__occupations"> {person.fields.occupation.map((occupation, index) => { return ( <span key={index} className="person__occupation"> {occupation} </span> ); })} </div> {/* Person's main content: name and biography */} <div className="person__content"> <h1 className="person__full-name">{person.fields.fullName}</h1> {/* Render biography as HTML content */} <div className="person__biography" dangerouslySetInnerHTML={{ __html: person.fields.biographyText.value }} /> </div> </div> ); } export default Person;
Obtener el código completado
El código fuente completo de este capítulo es disponible en Github.com.
$ git fetch --tags
$ git tag
$ git checkout tags/headless_open-api_basic_4-end
Pruebe la aplicación
Revise la aplicación http://localhost:3000/ y haga clic en los vínculos Miembro del equipo. Además, puede añadir más equipos o miembros a Team Alpha añadiendo fragmentos de contenido en el servicio de creación de AEM y publicándolos.
Internamente
Abra la consola Herramientas para desarrolladores > Red del explorador y Filtre para /adobe/contentFragments
solicitudes de captura al interactuar con la aplicación React.
Enhorabuena.
¡Enhorabuena! Ha creado correctamente una aplicación de React para consumir y mostrar fragmentos de contenido de la entrega de fragmentos de contenido de AEM con las API de OpenAPI.