Calling an action

👍

Prerequisites

If you want to trigger an operation on a backend system or want to fetch data asynchronously after initial rendering, you call an action extensionaction extension - A custom endpoint that can be called. It allows you to forward any kind of API calls to backend services, including writing data to it. (see the developing an action extension article for more information).

For this example, we'll use the following Frontastic componentFrontastic component - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. to implement searching a backend data set using an action:

import React from 'react';

const CharacterSearchTastic: React.FC = () => {
  return (
    <>
      <form
        onSubmit={(event) => {
          event.preventDefault();
        }}
      >
        <label>
          Search:
          <input type="text" name="search" />
        </label>
        <input type="submit" value="Search" />
      </form>
      <ul>
      </ul>
    </>
  );
};

export default CharacterSearchTastic
{
  "tasticType": "example/character-search",
  "name": "Character search",
  "category": "Example",
  "description": "A Frontastic component showing actions and session handling",
  "schema": []
}

The Frontastic componentFrontastic component - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. doesn't provide any configuration to Frontastic studio and (so far) only renders a rudimentary search form and an empty list.

Perform the fetch call

An action extensionaction extension - A custom endpoint that can be called. It allows you to forward any kind of API calls to backend services, including writing data to it. is a server function in the Frontastic API hubAPI hub - The API hub combines our code, your code, and APIs to create the backend of a commerce site. Any backend development or extensions are done here. Known as `Catwalk` in code. which can be invoked by a URL in the following format: https://<frontastic-host>/frontastic/action/<namespace>/<action>(also see the action API section).

To access it, you should always use the fetchApiHub() function:

import { fetchApiHub } from 'frontastic';

export const characterSearch = async (search: string) => {
  return await fetchApiHub('/action/star-wars/character?search=' + encodeURIComponent(search));
};

By convention, you should store the file to encapsulate the fetchApiHub() call in packages/<project>/frontend/frontastic/actions/.

📘

The fetchApiHub() function not only resolves the correct API hub host for you but also ensures to maintain the Frontastic sessionFrontastic session - The Frontastic session is stored in a cookie on the client side as JWT automatically persists information between Frontastic extension executions.. For this reason, you should always use the fetchApiHub() function for communication with the API hubAPI hub - The API hub combines our code, your code, and APIs to create the backend of a commerce site. Any backend development or extensions are done here. Known as `Catwalk` in code..

Register fetcher as a hook

The fetch function is wrapped into a higher-order component to receive the base URL to the Frontastic host to query. This way, it can be used together with the Frontastic provider component, where you should register your fetchers in the manner of ReactJS hooks:

// …
import { characterSearch } from '../actions/doc-character-search';
// …
export const FrontasticProvider: React.FC> = ({ children }) => {
  return (
    <SWRConfig value={{ fetcher: fetchApiHub }}>
      <FrontasticContext.Provider
        value={{
          // ...
          useStarWars: {
            characterSearch: characterSearch,
          },
        }}
      >
        {children}
      </FrontasticContext.Provider>
    </SWRConfig>
  );
};

// …
export const useStarWars = () => {
  const context = React.useContext(FrontasticContext);

  if (!context) throw new Error('Expected to be wrapped in FrontasticProvider');

  return context.useStarWars;
};

The code above needs to be added to the file packages/<project>/frontend/frontastic/lib/provider.tsx.

There are 2 steps:

  1. Register the characterSearch() function on the Frontastic context provider
  2. If not done yet, expose a fetcher function to make use of the functions in the corresponding hook

In this example, a new hook (useStarWars) is exposed for which a new provider property is used.

❗️

The way fetchers are registered in the lib/ folder will change soon.

Execute the hook to fetch search results

Based on this infrastructure code, you can now complete the Frontastic componentFrontastic component - A customizable building block that's used together with other components to create a commerce site. Known as `tastic` for short in code. and use the useState() hook to maintain the search results locally:

import React, { useState } from 'react';
import { useStarWars } from 'frontastic';

const CharacterSearchTastic: React.FC = () => {
  const { characterSearch } = useStarWars();
  const [searchResults, setSearchResults] = useState([]);

  return (
    <>
      <form
        onSubmit={(event) => {
          event.preventDefault();
          characterSearch(event.target[0].value).then((result) => {
            setSearchResults(result.results || []);
          });
        }}
      >
        <label>
          Search:
          <input type="text" name="search" />
        </label>
        <input type="submit" value="Search" />
      </form>
      <ul>
        {searchResults.map((character) => {
          return <li key={character.url}>{character.name}</li>;
        })}
      </ul>
    </>
  );
};

export default CharacterSearchTastic;

Did this page help you?