Data Fetching

Centralized service configurations with hooks for executing API requests.


Why This Pattern?

Instead of manual state management in every component:

const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const [error, setError] = useState(null);
// ... manual API calls

Use this:

const { loading, data, error } = useExecuteRequest(LocationServices.getAll());

Benefits: DRY, type-safe, auto state management, built-in debouncing/polling


Service Configurations

Define all API calls in services.ts:

// src/services.ts
import { ExecuteServiceConfig } from 'uxp/components';

export const LocationServices = {
  getAll: (params = {}): ExecuteServiceConfig => ({
    type: 'service',
    app: 'Location',
    service: 'Location:GetAllLocations',
    parameters: params,
    options: { json: true },
    defaultValue: []
  })
};

export const LocationTypeServices = {
  getAll: (): ExecuteServiceConfig => ({
    type: 'service',
    app: 'Location',
    service: 'LocationType:All',
    parameters: {
      __sort__: 'SortOrderValue',
      __sortorder__: 'asc'
    },
    options: { json: true },
    defaultValue: []
  }),

  create: (locationType: string): ExecuteServiceConfig => ({
    type: 'service',
    app: 'Location',
    service: 'LocationType:Create',
    parameters: { LocationType: locationType },
    options: { json: true }
  }),

  update: (locationType: LocationType): ExecuteServiceConfig => ({
    type: 'service',
    app: 'Location',
    service: 'LocationType:Update',
    parameters: {
      LocationTypeKey: locationType.LocationTypeKey,
      LocationType: locationType.LocationType
    },
    options: { json: true }
  }),

  delete: (locationType: LocationType): ExecuteServiceConfig => ({
    type: 'service',
    app: 'Location',
    service: 'LocationType:DeleteEx',
    parameters: {
      LocationTypeKey: locationType.LocationTypeKey
    },
    options: {}
  })
};

Config Types

Type
Use For

service

Lucy services: app: 'Location', service: 'Location:GetAll'

action

Model actions: model: 'Location', action: 'GetAll'

microservice

Microservices: serviceName: 'analytics', route: '/metrics'

api

Direct HTTP: url: 'https://api.example.com/data'

Key Options

  • defaultValue - Fallback when data is null or error

  • extractData - Extract specific data: [0], 'items', [0, 'items']

  • transformData - Transform data after extraction


Three Ways to Execute

1. useExecuteRequest Hook

Use when: Component needs loading/data/error state

2. executeConfig Function

Use when: Callbacks, event handlers, no state needed

3. useExecuteRequestCallback Hook

Use when: Need stable callback with dynamic parameters


Quick Reference

Tool
State Updates
Use Case

useExecuteRequest

✅ Auto

Component data loading

executeConfig

❌ None

Callbacks, event handlers

useExecuteRequestCallback

❌ None

Stable callbacks with params


Complete Example


Filter Patterns for ObjectSearchComponent

⚠️ CRITICAL: Common filter implementation mistakes

Understanding Filter Structure

Filters from ObjectSearchComponent are passed with nested structure:

Complete Filter Pattern

Paginated Select Fields

Use getPaginatedOptions with selectedOptionLabel:

Cascading Dropdowns

Use dependsOn for parent-child relationships:

Date Field Conversion

Date fields need ISO string conversion:

Common Mistakes

❌ WRONG
✅ CORRECT

filters?.UserKey

filters?.filters?.UserKey

serviceConfig: UserServices.getAll()

getPaginatedOptions: getUserOptions

keyField / textField

valueField / labelField

Missing selectedOptionLabel

Required for paginated selects

startOfDay(filters.StartDate)

startOfDay(new Date(filters.filters.StartDate)).toISOString()

[context, toast] in useCallback deps

[context] only


See Location 5.0 app (/Location/5.0/Resources/views/src/services.ts) for complete service configuration examples.


Next Steps

Last updated