Write a fetcher
Typically, a widget renders your page on the server as the initial display for the widget is generated. The data needed to do this is obtained using data fetchers.
There are many default data fetchers, which you can reference from the /oracle-cx-commerce/fetchers directory, but you can also create your own.
Data fetchers are plug-ins that can be included in your application to identify what your widget needs before it can be rendered. When you use a template to create a widget, the template pulls in all default fetchers. Fetchers that you create to use with your widget are stored in your application’s /plugins/fetchers directory.
widgetConfig parameter. Global fetchers can be used by any widget, or by multiple widgets simultaneously. This is a generic fetcher that loads the current site:const fetchSite = store => store.endpoint('getSite');The other type of fetcher is a component-specific fetcher, or one that is dependent on the widget configuration. These fetchers create requests that are specific to the widget instance and may return unique results per widget instance.
const fetchMenuCategories = (store, widgetConfig) => {
// Get the necessary values from widget config
const {numberOfChildCategoriesToDisplay = 3, hideCategoryIfOutOfStock = false} = widgetConfig;
// Pass the widget config values to the endpoint call
return store.endpoint('getCollectionMenu', {
categoryId: 'rootCategory',
filterKey: 'categoryNavData',
expandChildren: true,
maxLevel: numberOfChildCategoriesToDisplay,
disableActiveProdCheck: hideCategoryIfOutOfStock
});
};store.endpoint method. For example:interface Fetcher {
(store: Store, [widgetConfig: Object]): Promise<*>
}- Create the appropriate applications
/plugindirectory. - Once you have the application directory, create a directory named
/plugins/fetchers. This directory should contain anindex.jsthat contains the following:/** * References to the application's custom data fetchers. */ export {listCurrenciesFetcher} from './list-currencies'; - In the
/plugins/fetchersdirectory, create ahooks.jsfile that contains the following:/** * References to the application's custom data fetcher hooks. */ export {useListCurrenciesFetcher} from './list-currencies/hook'; - Now create a sub-directory within the
/plugins/fetchersdirectory, for example/plugins/fetchers/list-currencies/. This directory will also contain anindex.jsand ahook.jsfile. - Create the fetcher
index.jsfile. For example, create the/plugins/fetchers/list-currencies/index.jsfile:/** * Fetcher that requests the currency list using an endpoint. */ export const listCurrenciesFetcher = store => store.endpoint('_listCurrencies'); - Create the fetcher
hook.jsfile. The hook file allows fetchers to be run inside React components. Fetcher hooks are based on theuseEffecthook and run only in the browser. TheuseEffecthook allows you to invoke the fetcher only after the page has been rendered. For example, create the/plugins/fetchers/list-currencies/hook.jsfile:import {useEffect} from 'react'; import {isEmptyObject} from '@oracle-cx-commerce/utils/generic'; import {getCurrencies} from '../../selectors'; import {listCurrenciesFetcher} from '..'; /** * This hook will invoke the listCurrenciesFetcher if the currency * list is not already available in the application state. */ export const useListCurrenciesFetcher = store => useEffect(() => { if (isEmptyObject(getCurrencies(store.getState()))) { listCurrenciesFetcher(store); } }, [store]);
It is a good practice to conditionally invoke the fetcher in the hook.js file to ensure that the fetcher is not already executed on the server-side. The above example conditionally invokes the fetcher after the isEmptyObject validation.
For performance information, refer to Prevent useEffect() from executing unnecessarily.