C3 AI Documentation Home

SDL React hooks reference

This reference provides a comprehensive list of SDL React hooks for building C3 applications with React/TypeScript.

Core Hooks

FunctionDescriptionHow to Import
useC3Action(spec, invalidators?)Make network requests to C3 backend APIs (api/8/{typeName}/{actionName}). Returns { data, status, error } with automatic loading state management.import { useC3Action } from '@c3/ui/UiSdlUseC3Action';
useDispatch()Get Redux dispatch function with automatic metadata enrichment (adds current site ID to actions).import { useDispatch } from '@c3/ui/UiSdlUseDispatch';
useSelectedState(selector, equalityFn?)Select Redux state with optimized re-render behavior. Only triggers on reducer actions, not epic-only actions. Uses shallowEqual by default.import { useSelectedState } from '@c3/ui/UiSdlUseData';
useEpic(actionName, callback, deps, filter?)Listen for specific Redux actions through epic middleware. Automatically registers/unregisters listeners on mount/unmount with dependency tracking.import { useEpic } from '@c3/ui/UiSdlUseEpic';
useConfig(typeName, configPath, configId?, singleton?)Retrieve C3 Config values. Automatically fetches from server if not in Redux store. Returns null until loaded.import { useConfig } from '@c3/ui/UiSdlUseConfig';

Application State

FunctionDescriptionHow to Import
useApplicationMetadata()Access UiSdlApplicationState including theme, branding, and global application configuration.import { useApplicationMetadata } from '@c3/ui/UiSdlUseApplicationMetadata';

UI Utility Hooks

FunctionDescriptionHow to Import
useTranslate(componentProps?)Get translation function for internationalization. Returns translate({ key, default }, variables?) function.import { useTranslate } from '@c3/sdl-react/hooks';
useLocaleDateTimeFormat()Get locale-specific date/time formatting functions based on user preferences.import { useLocaleDateTimeFormat } from '@c3/sdl-react/hooks';
useEchartsTheme()Get ECharts theme configuration based on current application theme.import { useEchartsTheme } from '@c3/sdl-react/hooks';
useEchartsLocale()Get ECharts locale configuration for internationalized charts.import { useEchartsLocale } from '@c3/sdl-react/hooks';
FunctionDescriptionHow to Import
useRoutes()Access routing configuration and navigation utilities for SDL application routes.import { useRoutes } from '@c3/ui/UiSdlUseRoutes';

Usage Examples

useC3Action - Fetch C3 Data

TypeScript
import { useC3Action } from '@c3/ui/UiSdlUseC3Action';

function TurbineList() {
  const { data, status, error } = useC3Action({
    typeName: 'WindTurbine',
    actionName: 'fetch',
    argsArray: [{ limit: 10 }],
  });

  if (status === 'loading') return <div>Loading...</div>;
  if (status === 'error') return <div>Error: {error}</div>;

  return <ul>{data?.objs.map((t) => <li key={t.id}>{t.name}</li>)}</ul>;
}

useEpic - Listen to Actions

TypeScript
import { useEpic } from '@c3/ui/UiSdlUseEpic';
import { useState } from 'react';

function ActionLogger() {
  const [logs, setLogs] = useState([]);

  useEpic(
    'TURBINE_UPDATED',
    (action, state) => {
      setLogs((prev) => [...prev, `Updated: ${action.payload.id}`]);
    },
    [],
  );

  return (
    <div>
      {logs.map((log, i) => (
        <p key={i}>{log}</p>
      ))}
    </div>
  );
}

useSelectedState - Access Redux State

TypeScript
import { useSelectedState } from '@c3/ui/UiSdlUseData';

function Counter() {
  // RTK slice - returns plain JavaScript
  const counter = useSelectedState((state) => state.get('counter'));

  // SDL state - requires .toJS()
  const sdlData = useSelectedState((state) => state.getIn(['metadata', 'components', 'byId', 'MyComponent'])?.toJS());

  return <div>Count: {counter?.value}</div>;
}

useConfig - Access Configuration

TypeScript
import { useConfig } from '@c3/ui/UiSdlUseConfig';

function AppSettings() {
  const apiUrl = useConfig('UiSdlConfig', 'apiUrl', null, true);
  const theme = useConfig('UiSdlConfig', 'theme', null, true);

  if (!apiUrl) return <div>Loading config...</div>;

  return (
    <div>
      API: {apiUrl}, Theme: {theme}
    </div>
  );
}

useDispatch - Dispatch Actions

TypeScript
import { useDispatch } from '@c3/ui/UiSdlUseDispatch';
import { increment } from '@c3/app/ui/src/slices/counter';

function CounterControls() {
  const dispatch = useDispatch();

  return (
    <div>
      <button onClick={() => dispatch(increment())}>Increment RTK</button>
      <button onClick={() => dispatch({ type: 'LEGACY_ACTION', payload: {} })}>Dispatch SDL Action</button>
    </div>
  );
}

useTranslate - Internationalization

TypeScript
import { useTranslate } from '@c3/sdl-react/hooks';

function Welcome() {
  const translate = useTranslate();

  return (
    <div>
      <h1>{translate({ key: 'WELCOME_MESSAGE', default: 'Welcome' })}</h1>
      <p>{translate({ key: 'GREETING', default: 'Hello {name}' }, { name: 'User' })}</p>
    </div>
  );
}

Common Patterns

Accessing Route Parameters

TypeScript
// SDL pattern
import { useSelector } from 'react-redux';
import { getPageParamFromState } from '@c3/ui/UiSdlConnected';

function TurbineDetails() {
  const id = useSelector((state) => getPageParamFromState(state, 'id'));

  const { data } = useC3Action({
    typeName: 'WindTurbine',
    actionName: 'get',
    argsArray: [{ id }],
  });

  return <div>{data?.name}</div>;
}

Shared State Management

Create an RTK slice:

TypeScript
// ui/c3/src/slices/counter.ts
import { createSlice } from '@reduxjs/toolkit';

export const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
  },
});

export const { increment } = counterSlice.actions;
export default counterSlice.reducer;

Use in a component:

TypeScript
import { useSelectedState } from '@c3/ui/UiSdlUseData';
import { useDispatch } from '@c3/ui/UiSdlUseDispatch';
import { increment } from '@c3/app/ui/src/slices/counter';

function Counter() {
  const count = useSelectedState((state) => state.get('counter')?.value);
  const dispatch = useDispatch();

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => dispatch(increment())}>Increment</button>
    </div>
  );
}

Best Practices

  1. State Selection: Use useSelectedState instead of react-redux's useSelector for better performance in SDL applications.

  2. C3 API Calls: Always prefer useC3Action over manual fetch/axios calls when calling C3 backend APIs.

  3. Config Access: Use useConfig('UiSdlConfig', 'key', null, true) with singleton pattern for app-wide configs for best performance.

  4. Epic Listeners: Keep deps array minimal and use useCallback for callback functions when dependencies are needed.

  5. RTK State vs SDL State:

    • RTK slices: state.get('sliceName') returns plain JavaScript
    • SDL state: state.getIn([...])?.toJS() requires .toJS() conversion
  6. Dependency Arrays: Always provide correct dependency arrays to hooks like useEpic to avoid stale closures.

  7. Type Safety: Import hooks from @c3/ui/* types (e.g., UiSdlUseC3Action) for TypeScript support.

Was this page helpful?