---
name: "useStructuredActions"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.10.0" }
title: "useStructuredActions - Implemented based on the sdm instance and dp-kit interceptor"
summary: "useStructuredActions is a React Hook provided by @ray-js/panel-sdk, implemented based on the sdm instance and dp-kit interceptor. It automatically converts structured data into device-recognizable DP commands and dispatches them according to the protocols file (e.g. actions.colour_data.set({ hue, saturation, value })). It only returns dispatch methods for DPs that have protocol rules configured. Supports both single devices and groups, and is commonly used together with useStructuredProps."
questions:
  - "How to publish raw type DPs? How to publish structured complex type DPs?"
  - "How does useStructuredActions automatically convert structured complex type DP data according to the protocols file and dispatch it?"
  - "How does actions.colour_data.set({ hue, saturation, value }) convert structured data into device-recognizable DP commands?"
  - "useStructuredActions only returns dispatch methods for DPs with protocol rules configured, not basic types. Why?"
  - "Before using useStructuredActions, you need to configure and integrate the dp-kit interceptor. Where is it configured?"
  - "What is the difference between useStructuredActions and useActions (structured complex type dispatch vs basic DP dispatch)?"
  - "useStructuredActions takes no arguments. How is the return type GetStructuredActions derived from the protocol?"
  - "How to use useStructuredProps and useStructuredActions together to read and dispatch colour light DP values?"
  - "useStructuredActions supports both single devices and groups. Will dispatched commands be sent to all sub-devices in a group?"
  - "For more information on useStructuredActions, refer to the dp-kit interceptor docs. What DP processing capabilities does dp-kit provide?"
  - "When dispatching colour_data via useStructuredActions, is the range of hue 0-360 and saturation/value 0-1000?"
---

<div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>
  <span style={{ backgroundColor: '#52c41a', color: 'white', padding: '2px 8px', borderRadius: '4px', fontSize: '12px' }}>Device Support</span>
  <span style={{ backgroundColor: '#52c41a', color: 'white', padding: '2px 8px', borderRadius: '4px', fontSize: '12px' }}>Group Support</span>
</div>

## useStructuredActions

> [VERSION] @ray-js/panel-sdk >= 1.10.0

> 💡 Implemented based on the sdm instance and the dp-kit interceptor. Must be used inside SdmProvider.
> Before using, ensure the project has mounted SdmProvider; see [Smart Device Model - Usage](/cn/miniapp/solution-panel/ability/common/sdm/usage). New projects can start from the [public-sdm](https://github.com/Tuya-Community/tuya-ray-materials/tree/main/template/PublicSdmTemplate) example.
> Ensure the dp-kit interceptor has been configured; see [Interceptors - Usage](/cn/miniapp/solution-panel/ability/common/sdm/interceptors/usage).
> Only send methods for DPs with protocol rules are returned; basic-type DPs are excluded (use useActions for basic types).
> Supports both single devices (SmartDeviceModel) and groups (SmartGroupModel). Symmetric with useStructuredProps: useStructuredProps reads structured data via Transformer.parser(), while useStructuredActions formats structured data into DP commands via Transformer.formatter().

### Description

Get the collection of structured DP send methods after dp-kit protocol transformation

### Parameters

None


### Return Value

Type: `Record<DpCode, { set: (value: object, options?: SendDpOption) => Promise<boolean> }>`

A collection of structured DP send methods. The key is a DP code configured with protocols; each key provides a set(structuredValue) method. The input type of set is determined by the parameter type of the corresponding Transformer.formatter(); internally it calls formatter to convert structured data to a DP string before sending to the device

### Referenced Types

##### `type` SendDpOption

DP send options. Can be used as the global default configuration for createDpKit, and can also be overridden in a single publishDps/action call.
The global `sendDpOption` suits product-level defaults;
options passed for a single send are suitable for temporarily overriding throttling, debouncing, protocol parsing, or optimistic update strategies.
Note: requires the dp-kit interceptor.

| Property | Type | Since | Description |
| --- | --- | --- | --- |
| `immediate` | `boolean` | - | Whether to trigger a state update immediately; requires the dp-kit interceptor |
| `ignoreDpDataResponse` | `boolean \| IgnoreDpChangeInterceptorOptions` | `1.11.0` | Whether to ignore DP reports; default false |
| `synchronizeDevProperty` | `boolean \| DevPropInterceptorOptions` | `1.11.0` | Whether to sync dpData with cloud device properties; default false |
| `ordered` | `boolean` | - | Whether to send multiple DPs in the order of the object’s keys; requires the dp-kit interceptor; default false |
| `checkRepeat` | `boolean` | - | Whether to check for duplicate values and skip sending; requires the dp-kit interceptor; default false Compared with the current `dpState`; duplicates are detected and not sent |
| `delay` | `number` | - | Delayed send; requires the dp-kit interceptor; default 0, in ms |
| `throttle` | `number` | - | Send throttling (conflicts with debounce); requires the dp-kit interceptor; default 0, in ms |
| `debounce` | `number` | - | Send debounce (conflicts with throttle); requires the dp-kit interceptor; default 0, in ms |
| `protocols` | `Record<string, CustomRawDpMap>` | - | A per-call DP protocol converter; requires the dp-kit interceptor. The key is the dpCode and the value is a `{ parser, formatter }` object: - parser(dpValue: string) => any — parses the raw DP string into a structured object - formatter(parsedValue: any) => string — serializes the structured object into a DP string Affects only this invocation and does not override the global protocols configuration in createDpKit |

##### `type` IgnoreDpChangeInterceptorOptions

Configuration option to ignore the DP data change interceptor

Used to configure the debounce mechanism for DP reporting events on the device panel, preventing immediate responses after panel operations from affecting user experience or business logic

| Property | Type | Description |
| --- | --- | --- |
| `whiteDpCodes` | `string[]` | DP whitelist; reports will not be ignored |
| `timeout` | `number` | Debounce timeout check, in milliseconds, default 5000 - The maximum time between sending a DP from the panel and receiving the DP reply; dpDataChange is triggered only if this is exceeded. - Used to debounce DP reporting events |
| `customRule` | `(dpState: DpState, lastSendTimestamp: number) => boolean` | Custom ignore rules > Highest priority; when configured, whiteDpCodes and timeout become ineffective |

##### `type` DevPropInterceptorOptions

| Property | Type | Description |
| --- | --- | --- |
| `blackDpCodes` | `string[]` | DP blacklist; will not be synchronized to the cloud |
| `defaultState` | `DpState` | Default device state on first entry; supports async initialization |
| `throttle` | `number` | Send throttling, in milliseconds, defaults to 0 If set to 0, throttling is disabled. |

##### `type` DpState

Datapoint status object, where the key is the datapoint code and the value is the datapoint value.

```typescript
export type DpState = Record<string, DpValue>;
```

##### `type` CustomRawDpMap

Custom DP protocol converter for transforming between raw DP strings and structured objects.
Suitable for composite DPs of type raw/string (e.g., a light's colour_data "00ff003e8"),
splitting a single string into multiple semantic fields (e.g., { hue, saturation, value }).

| Property | Type | Description |
| --- | --- | --- |
| `parser` | `(dpValue: string) => any` | Parse the raw DP string reported by the device into a structured object |
| `formatter` | `(parsedDpValue: any) => string` | Serialize the structured object into a DP string to be sent to the device |

##### `interface` DpSchema

| Property | Type | Description |
| --- | --- | --- |
| `attr` | `number` | DP attribute flag bit, used to mark additional capabilities of the DP |
| `canTrigger` | `boolean` | Whether it can be used as an automation trigger condition |
| `code` | `string` | DP code, e.g., switch |
| `defaultRecommend` | `boolean` | Whether it is the default recommended DP |
| `editPermission` | `boolean` | Whether it has edit permission |
| `executable` | `boolean` | Whether it can be issued (sent downstream) |
| `extContent` | `string` | DP extension content, typically a JSON string |
| `iconname` | `string` | DP icon name |
| `id` | `string \| number` | DP ID |
| `mode` | `"rw" \| "ro" \| "wr"` | DP mode type rw: writable and reportable (read/write) ro: report-only (read-only) wr: write-only |
| `name` | `string` | DP name, typically used in voice scenarios |
| `property` | `Object` | DP attributes |
| `type` | `"raw" \| "obj"` | DP data type categories: raw for raw byte stream, obj for structured object |

##### `type` DpValue

Datapoint value type, which can be boolean, number, or string.

```typescript
export type DpValue = boolean | number | string;
```

##### `type` DpSchema.property

| Property | Type | Description |
| --- | --- | --- |
| `type` | `"string" \| "bool" \| "value" \| "enum" \| "bitmap" \| "raw"` | DP type |
| `range` | `string[] \| string[]` | Enum value range; present only when type = enum |
| `label` | `string[] \| string[]` | Fault label list; present only when type = bitmap |
| `maxlen` | `number` | Maximum length for fault bitmap; present only when type = bitmap |
| `unit` | `string` | Unit (type = value only) |
| `min` | `number` | Minimum value (type = value only) |
| `max` | `number` | Maximum value (type = value only) |
| `scale` | `number` | Precision (type = value only) |
| `step` | `number` | Step (type = value only) |


### Examples

#### Full flow: read + send (using lighting colour_data as an example)

```tsx
// ---- 1. devices/protocols/index.ts: Instantiate the parser and map it to the DP code ----
import { protocols as sdkProtocols } from '@ray-js/panel-sdk';
import { lampSchemaMap } from '../schema';

export const protocols = {
  [lampSchemaMap.colour_data.code]: new sdkProtocols.ColourTransformer(),
  // ColourTransformer.parser() returns { hue, saturation, value } → read via useStructuredProps
  // ColourTransformer.formatter() accepts { hue, saturation, value } → write via useStructuredActions
};

// ---- 2. devices/index.ts: Create dpKit and pass it to the sdm instance ----
import { SmartDeviceModel, createDpKit } from '@ray-js/panel-sdk';
import { protocols } from '@/devices/protocols';

export const dpKit = createDpKit({ protocols });
export const devices = {
  lamp: new SmartDeviceModel({ interceptors: dpKit.interceptors }),
};

// ---- 3. Page component: Send structured data via useStructuredActions ----
import { View, Text } from '@ray-js/ray';
import { useStructuredProps, useStructuredActions } from '@ray-js/panel-sdk';

export default function Home() {
  // Read: parser() return value determines the type of colour: { hue, saturation, value }
  const colour = useStructuredProps(props => props.colour_data);
  // Write: set() parameter type equals formatter()'s parameter type, both are { hue, saturation, value }
  const actions = useStructuredActions();

  return (
    <View onClick={() => actions.colour_data.set({ hue: 120, saturation: 800, value: 900 })}>
      <Text>Hue: {colour.hue}</Text>
      <Text>Saturation: {colour.saturation}</Text>
      <Text>Value: {colour.value}</Text>
    </View>
  );
}
```
