Passing Data from Server to the React App

This article shows how to pass json data from Express.js or AEM backend to the React app.

Jakub Olszyna
Adobe Tech Blog

--

A common use case for web applications is displaying an authenticated user’s profile data. In this article, I will show you how to create a React client application backed by an Express or AEM server and consume user profile data from the server in each of the two configurations.

Client

First let’s create a client application using Create React App:

npx create-react-app client

Assuming that user data from the server are available through the window object, creating Context provider makes it possible to initialise the app with user data and then use them throughout the application.

// client/AppContext.jsimport React, { createContext, useState } from 'react';const AppContext = createContext();
const user = window.__user || { displayName: 'Anonymous' };const INIT_STATE = { user };const AppContextProvider = ({ children }) => { const [app, setApp] = useState(INIT_STATE); return (
<AppContext.Provider value={{ app, setApp }}>
{children}
</AppContext.Provider>
);
};
const AppContextConsumer = AppContext.Consumer;export { AppContext, AppContextProvider, AppContextConsumer };
export default AppContext;

To use the newly created provider let’s modify the App.js and add AppContextProvider so that all the child views have access to the app context.

// client/App.jsimport './App.css';import { AppContextProvider } from './AppContext'import View from './View';
function App() { return ( <AppContextProvider> <View /> </AppContextProvider> );}export default App;

User data from the app context is displayed by the simple view component.

// client/View.jsimport React, { useContext } from 'react';import AppContext from './AppContext';
const View = ({ children }) => { const { app } = useContext(AppContext); const { user } = app; return ( <div> Hello, { user.displayName }!</div> );};export default View;

At this point we can test everything out by running yarn start. Since there is no server the default message should appear in the browser (http://localhost:3000/)

Hello, Anonymous!

Server

Once we have the client app ready, we need to create a server that will handle all the logic.

Express.js

Let’s create a server using express-generator with ejs view engine enabled:

express --view=ejs server

Assuming we have the user data as json, we can prepare a html view with a script adding the user object to the window. To make it work user object needs to be stringified and then parsed . Including html file from the client makes the entire React application load.

<!-- views/index.ejs --><!doctype html><html lang="en"><head>   <script type="text/javascript">      window.__user = JSON.parse(`<%- JSON.stringify(user); %>`);   </script></head><%- include('../../client/build/client.html')%></html>

To render html properly and serve static files from out React app, the app.js needs to be modified a bit:

// server/app.jsapp.engine('html', require('ejs').renderFile);...app.use(express.static(path.join(__dirname, '../client/build/')))

Now the actual user object needs to be passed to the render function:

// server/routes/index.jsrouter.get('/', function(req, res, next) {   res.render('index', { user: { displayName: 'John Smith' } });});

The last step is modifying the client package.json with postbuild script renaming the index.html to client.html, which prevents the file from being overwritten:

// client/package.json"postbuild": "mv build/index.html build/client.html"

After building the client and running the server an updated user greeting should be displayed (http://localhost:3000/)

Hello, John Smith!

AEM

As an alternative to Express.js server let’s create an AEM project:

mvn -B archetype:generate \
-D archetypeGroupId=com.adobe.aem \
-D archetypeArtifactId=aem-project-archetype \
-D archetypeVersion=24 \
-D appTitle="My Site" \
-D appId="mysite" \
-D groupId="com.mysite" \
-D frontendModule="react"

Since the react frontend module was selected, our client app can just be copied to /mysite/ui.frontend/src. This time user data need to be set within a script (in real life scenario this script would fetch the data from AEM user profile).

// /apps/mysite/components/page/user.js'use strict'

use(function() {

return {
displayName: 'John Smith'
}
})

To make the data available let’s find the page template and modify the header:

<!-- /apps/mysite/components/page/customheaderlibs.html -->
<sly data-sly-use.user="user.js"></sly>
<script>
window.__user = {
displayName: '${user.displayName @ context="scriptString"}'
};
</script>

After triggering the Maven build and deploying everything to the AEM the same greeting as for the Express.js use case should appear (http://localhost:4502/content/mysite/us/en/home.html)

Hello, John Smith!

Conclusions

Congrats, you are now able to pass json data from Express.js or AEM backend to your React app!

References

  1. https://www.npmjs.com/package/express-generator
  2. https://github.com/adobe/aem-project-archetype
  3. https://create-react-app.dev/docs/getting-started/

--

--