Install headless Optimizely Forms JavaScript SDK for the client app
5 min
Precondition: npm install -g typescript
- Create a React app template.
npx create-react-app headless-form --template typescript
cd headless-form- Install Javascript SDK. Create a file .npmrc with content to download the package from GitHub.
@episerver:registry=https://pkgs.dev.azure.com/EpiserverEngineering/netCore/_packaging/HeadlessForms/npm/registrynpm install @episerver/forms-sdk @episerver/forms-react react-router-dom @types/react-router-domNote Replace the react-router-dom with version =5.3.4.
- Create file .env with content.
REACT_APP_ENDPOINT_GET_FORM_BY_PAGE_URL=http://localhost:8000/api/React/GetFormInPageByUrl?url=
REACT_APP_HEADLESS_FORM_BASE_URL=http://localhost:8000/
REACT_APP_AUTH_BASEURL=http://localhost:8000/api/episerver/connect/token- Add code to \src\App.tsx.
import "./App.css";
import { useFetch } from "./useFetch";
import { Form, FormLogin } from "@episerver/forms-react";
import {
FormCache,
FormConstants,
IdentityInfo,
extractParams,
} from "@episerver/forms-sdk";
import { useState } from "react";
import { useHistory, useLocation } from "react-router-dom";
function App() {
const location = useLocation();
const { language } = extractParams(window.location.pathname);
const url = `${process.env.REACT_APP_ENDPOINT_GET_FORM_BY_PAGE_URL}${location.pathname}`;
const { data: pageData, loading } = useFetch(url);
const formCache = new FormCache();
const [identityInfo, setIdentityInfo] = useState<IdentityInfo>({
accessToken: formCache.get<string>(FormConstants.FormAccessToken),
} as IdentityInfo);
const history = useHistory();
const handleAuthen = (identityInfo: IdentityInfo) => {
setIdentityInfo(identityInfo);
};
return (
<div className="App">
{loading && <div className="loading">Loading...</div>}
{!loading && pageData && (
<>
<h1>{pageData.title}</h1>
<div className="main">
<div className="left">
{pageData.formKeys.map((c: any) => (
<Form
key={c.reference.key}
formKey={c.reference.key}
language={language ?? "en"}
baseUrl={process.env.REACT_APP_HEADLESS_FORM_BASE_URL ?? "/"}
identityInfo={identityInfo}
history={history}
currentPageUrl={pageData.pageUrl}
/>
))}
</div>
<div className={`right`}>
<h2>Login</h2>
<FormLogin
clientId="TestClient"
authBaseUrl={process.env.REACT_APP_AUTH_BASEURL ?? ""}
onAuthenticated={handleAuthen}
/>
</div>
</div>
</>
)}
</div>
);
}
export default App;
- Remove App.test.tsx file.
- Update code \src\index.tsx.
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
<Router>
<Switch>
<Route path="/">
<App />
</Route>
</Switch>
</Router>
</React.StrictMode>
);- Add file \src\useFetch.ts.
import { useEffect, useState } from "react";
export const useFetch = (url: string) => {
const [data, setData] = useState<any>(null);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<any>(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
fetch(url)
.then(async (response: Response) => {
if (response.ok) {
setData(await response.json());
}
})
.catch((err: any) => {
setError(err);
})
.finally(() => {
setLoading(false);
});
};
if (!loading) {
fetchData();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url]);
return { data, loading, error };
};
- Run client site.
npm start- Change the frontend's port to ClientApp's port on ManagementSite.
- Update appsettings.json file.
- Update on Manage Websites.
- Use http instead of https on launchSettings.json.