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
/plugin
directory. - Once you have the application directory, create a directory named
/plugins/fetchers
. This directory should contain anindex.js
that contains the following:/** * References to the application's custom data fetchers. */ export {listCurrenciesFetcher} from './list-currencies';
- In the
/plugins/fetchers
directory, create ahooks.js
file 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/fetchers
directory, for example/plugins/fetchers/list-currencies/
. This directory will also contain anindex.js
and ahook.js
file. - Create the fetcher
index.js
file. For example, create the/plugins/fetchers/list-currencies/index.js
file:/** * Fetcher that requests the currency list using an endpoint. */ export const listCurrenciesFetcher = store => store.endpoint('_listCurrencies');
- Create the fetcher
hook.js
file. The hook file allows fetchers to be run inside React components. Fetcher hooks are based on theuseEffect
hook and run only in the browser. TheuseEffect
hook allows you to invoke the fetcher only after the page has been rendered. For example, create the/plugins/fetchers/list-currencies/hook.js
file: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.