AEM Headless APIs and React
Welcome to this tutorial chapter where we will explore configuring a React app to connect with Adobe Experience Manager (AEM) Headless APIs using the AEM Headless SDK. We’ll cover retrieving Content Fragment data from AEM’s GraphQL APIs and displaying it in the React app.
AEM Headless APIs allow accessing AEM content from any client app. We’ll guide you through configuring your React app to connect to AEM Headless APIs using the AEM Headless SDK. This setup establishes a reusable communication channel between your React app and AEM.
Next, we’ll use the AEM Headless SDK to retrieve Content Fragment data from AEM’s GraphQL APIs. Content Fragments in AEM provide structured content management. By utilizing the AEM Headless SDK, you can easily query and fetch Content Fragment data using GraphQL.
Once we have the Content Fragment data, we’ll integrate it into your React app. You’ll learn how to format and display the data in an appealing manner. We’ll cover best practices for handling and rendering Content Fragment data in React components, ensuring a seamless integration with your app’s UI.
Throughout the tutorial, we’ll provide explanations, code examples, and practical tips. By the end, you’ll be able to configure your React app to connect to AEM Headless APIs, retrieve Content Fragment data using the AEM Headless SDK, and seamlessly display it in your React app. Let’s get started!
Clone the React app
-
Clone the app from Github by executing the following command on the command line.
code language-none $ git clone git@github.com:lamontacrook/headless-first.git
-
Change into the
headless-first
directory, and install the dependencies.code language-none $ cd headless-first $ npm ci
Configure the React app
-
Create a file named
.env
at the root of the project. In.env
set the following values:code language-none REACT_APP_AEM=<URL of the AEM instance> REACT_APP_ENDPOINT=<the name of the endpoint> REACT_APP_PROJECT=<the name of the folder with Content Fragments> REACT_APP_TOKEN=<developer token>
-
You can retrieve a developer token in Cloud Manager. Log in to Adobe Cloud Manager. Click Experience Manager > Cloud Manager. Choose the appropriate Program and then click the ellipses next to the Environment.
- Click in the Integrations tab
- Click Local Token tab & Get Local Development Token button
- Copy the access token beginning after the open quote until before the close quote.
- Paste the copied token as the value for
REACT_APP_TOKEN
in the.env
file. - Let’s now build the app by executing
npm ci
on the command line. - Now start the React app and by executing
npm run start
on the command line. - In ./src/utils a file named
context.js
includes the code to set the values in the.env
file into the context of the app.
Run the React app
-
Start the React app by executing
npm run start
on the command line.code language-none $ npm run start
The React app will start and open a browser window to
http://localhost:3000
. Changes to the React app will be automatically reloaded in the browser.
Connect to AEM Headless APIs
-
To connect the React app to AEM as a Cloud Service, let’s add a few things to
App.js
. In theReact
import, adduseContext
.code language-javascript import React, {useContext} from 'react';
Import
AppContext
from thecontext.js
file.code language-javascript import { AppContext } from './utils/context';
Now within the app code, define a context variable.
code language-javascript const context = useContext(AppContext);
And, finally wrap the return code in
<AppContext.Provider> ... </AppContext.Provider>
.code language-javascript ... return(<div className='App'> <AppContext.Provider value={context}> ... </AppContext.Provider> </div>);
For reference, the
App.js
should now be like this.code language-javascript import React, {useContext} from 'react'; import './App.css'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Home from './screens/home/home'; import { AppContext } from './utils/context'; const App = () => { const context = useContext(AppContext); return ( <div className='App'> <AppContext.Provider value={context}> <BrowserRouter> <Routes> <Route exact={true} path={'/'} element={<Home />} /> </Routes> </BrowserRouter> </AppContext.Provider> </div> ); }; export default App;
-
Import the
AEMHeadless
SDK. This SDK is a helper library used by the app to interact with AEM’s Headless APIs.Add this import statement to the
home.js
.code language-javascript import AEMHeadless from '@adobe/aem-headless-client-js';
Add the following
{ useContext, useEffect, useState }
to theReact
import statement.code language-javascript import React, { useContext, useEffect, useState } from 'react';
Import the
AppContext
.code language-javascript import { AppContext } from '../../utils/context';
Inside the
Home
component, get thecontext
variable from theAppContext
.code language-javascript const Home = () => { const context = useContext(AppContext); ... }
-
Initialize the AEM Headless SDK inside a
useEffect()
, since the AEM Headless SDK must change when thecontext
variable changes.code language-javascript useEffect(() => { const sdk = new AEMHeadless({ serviceURL: context.url, endpoint: context.endpoint, auth: context.token }); }, [context]);
note note NOTE There is a context.js
file under/utils
that is reading elements from the.env
file. For reference, thecontext.url
is the URL of the AEM as a Cloud Service environment. Thecontext.endpoint
is the full path to the endpoint created in the previous lesson. Lastly, thecontext.token
is the developer token. -
Create React state that exposes the content coming from the AEM Headless SDK.
code language-javascript const Home = () => { const [content, setContent] = useState({}); ... }
-
Connect the app to AEM. Use the persisted query created in the previous lesson. Let’s add the following code inside the
useEffect
after the AEM Headless SDK is initialized. Make theuseEffect
dependent on thecontext
variable as seen below.code language-javascript useEffect(() => { ... sdk.runPersistedQuery('<name of the endpoint>/<name of the persisted query>', { path: `/content/dam/${context.project}/<name of the teaser fragment>` }) .then(({ data }) => { if (data) { setContent(data); } }) .catch((error) => { console.log(`Error with pure-headless/teaser. ${error.message}`); }); }, [context]);
-
Open the developer tools’ Network view to review the GraphQL request.
<url to environment>/graphql/execute.json/pure-headless/teaser%3Bpath%3D%2Fcontent%2Fdam%2Fpure-headless%2Fhero
The AEM Headless SDK encodes the request for GraphQL and adds the provided parameters. You may open the request in the browser.
note note NOTE Since the request is going to the author environment, you must be logged into the environment in another tab of the same browser.
Render Content Fragment content
-
Display the Content Fragments in the app. Return a
<div>
with the teaser’s title.code language-javascript return ( <div className='main-body'> <div>{content.component && (content.component.item.title)}</div> </div> );
You should see the title field of the teaser displayed on the screen.
-
The last step, is to add the teaser to the page. A React teaser component is included in the package. First, let’s include the import. At the top of the
home.js
file, add the line:import Teaser from '../../components/teaser/teaser';
Update the return statement:
code language-javascript return ( <div className='main-body'> <div>{content.component && <Teaser content={content.component.item} />}</div> </div> );
You should now see the teaser with the content included within the fragment.
Next Steps
Congratulations! You’ve successfully updated the React app to integrate with AEM Headless APIs using the AEM Headless SDK!
Next, let’s create a more complex Image List component that dynamically renders referenced Content Fragments from AEM.
Next Chapter: Build an Image List component