HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Install headless Optimizely Forms JavaScript SDK for the client app

Precondition: npm install -g typescript

  1. Create a React app template.

    npx create-react-app headless-form --template typescript
    cd headless-form
    
  2. 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/registry
    

    npm install @episerver/forms-sdk @episerver/forms-react react-router-dom @types/react-router-dom
    

    📘

    Note

    Replace the react-router-dom with version =5.3.4.

  3. 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
    
  4. 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;
    
    
  5. Remove App.test.tsx file.

  6. 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>
    );
    
  7. 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 };
    };
    
    
  8. Run client site.

    npm start
    
  9. 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.