---
name: "useStructuredProps"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.10.0" }
title: "useStructuredProps - Implemented based on the sdm instance and dp-kit interceptor"
summary: "useStructuredProps is a React Hook provided by @ray-js/panel-sdk, implemented based on the sdm instance and dp-kit interceptor. It automatically parses complex type DPs (e.g. colour_data into hue/saturation/value) according to the protocols file. Use a selector to subscribe to state changes and trigger re-renders. Built-in shallow equal with support for a custom equalityFn. Only returns DPs that have protocol rules configured. Supports both single devices and groups."
questions:
  - "How to listen for structured complex type DP state changes? How to listen for raw type DP state changes?"
  - "How does useStructuredProps automatically parse colour_data into hue, saturation, value structure according to the protocols file?"
  - "useStructuredProps only returns DPs with protocol rules configured, not basic data type DPs. Why?"
  - "Before using useStructuredProps, you need to configure and integrate the dp-kit interceptor. Where is it configured?"
  - "useStructuredProps has built-in shallow equal comparison. How to re-render only when colour.hue changes via a custom equalityFn?"
  - "What is the type GetStructuredDpState of the selector function parameter props in useStructuredProps, and how is it derived from the protocol?"
  - "What is the difference between useStructuredProps and useProps (structured complex types vs basic DPs)?"
  - "useStructuredProps supports both single devices and groups. Is the usage consistent in both environments?"
  - "What do the TypeScript generics DpKitProtocols and DpValue of useStructuredProps represent?"
  - "How to subscribe to real-time state of a colour light DP via useStructuredProps(props => props.colour_data)?"
  - "For more information on useStructuredProps, refer to the dp-kit interceptor docs. What DP processing capabilities does dp-kit provide?"
---

<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>

## useStructuredProps

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

> 💡 Implemented on top of the sdm instance and the dp-kit interceptor. Must be used inside SdmProvider.
> Before using, make sure SdmProvider has been mounted. For integration, see [Smart Device Model - Usage](/cn/miniapp/solution-panel/ability/common/sdm/usage). For new projects, you can develop directly based on the [public-sdm](https://github.com/Tuya-Community/tuya-ray-materials/tree/main/template/PublicSdmTemplate) example.
> Before using, also make sure the dp-kit interceptor is configured; see [Interceptors - Usage](/cn/miniapp/solution-panel/ability/common/sdm/interceptors/usage).
> For simplicity and stability, useStructuredProps only returns DPs that have protocol rules configured; it does not return basic data-type DPs.
> Typical scenario: composite string fields such as colour_data are automatically parsed by dp-kit according to protocols into structured objects like
> { hue, saturation, value }.

### Description

Get the structured DP state parsed by dp-kit protocols; when the state changes, it triggers component re-rendering

### Parameters

`Params`

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `selector` | `(structuredProps: object) => any` | No | Selector function. Input: the structured state object (the value type of each key is determined by the return value of the corresponding Transformer.parser() in protocols). Return the part to subscribe to; if omitted, returns the entire structured DP state. Note: basic data-type DPs are not returned. |
| `equalityFn` | `(prev: any, next: any) => boolean` | No | Custom comparator. Inputs are the previous and next selector return values; return true to skip re-rendering. Defaults to shallow equal |

### Return Value

Type: `any`

The selector’s return value, with type determined by the selector; if no selector is provided, returns the full structured state object (the value type of each key equals the return type of the corresponding Transformer.parser()).

### Examples

#### End-to-end access flow (using lighting colour_data as an example)

```ts
// ---- 1. Parser: Reference to the SDK's built-in ColourTransformer source ----
// Transformer interface: { uuid, defaultValue, parser(dpStr) → T, formatter(data: T) → string }
// The return type T of parser determines the structured type of the corresponding DP code in useStructuredProps
// Custom parsers are similar—implement both parser and formatter
type TColorData = { hue: number; saturation: number; value: number };

class ColourTransformer implements Transformer<TColorData> {
  defaultValue = { hue: 10, saturation: 1000, value: 1000 };
  uuid = 'colour_data';

  // parser returns TColorData → in useStructuredProps, props.colour_data is of this type
  parser(value: string): TColorData {
    if (value.length !== 12) return this.defaultValue;
    const step = generateDpStrStep(value);
    return { hue: step(4).value, saturation: step(4).value, value: step(4).value };
  }

  formatter(data: TColorData) {
    const { hue, saturation, value } = data;
    return `${decimalToHex(hue, 4)}${decimalToHex(saturation, 4)}${decimalToHex(value, 4)}`;
  }
}

// ---- 2. 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 = {
  // The actual variable name is colour_data, mapped to the DP code
  [lampSchemaMap.colour_data.code]: new sdkProtocols.ColourTransformer(),
};

// ---- 3. 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 }),
};

// ---- 4. Page component: Consume structured data via useStructuredProps ----
// The type of props.colour_data equals the return type TColorData of ColourTransformer.parser()
// i.e., { hue: number; saturation: number; value: number }
import { useStructuredProps } from '@ray-js/panel-sdk';
export default function Home() {
  const colour = useStructuredProps(props => props.colour_data);
  return (
    <View>
      <View>Hue: {colour.hue}</View>
      <View>Saturation: {colour.saturation}</View>
      <View>Value: {colour.value}</View>
    </View>
  );
}
```

#### Custom rerender

```tsx
import React from 'react';
import { View } from '@ray-js/ray';
import { useStructuredProps } from '@ray-js/panel-sdk';

export default function Home() {
  const dpState = useStructuredProps(
    d => d,
    (prevDpState, nextDpState) => prevDpState.colour_data?.hue === nextDpState.colour_data?.hue, // Rerenders only when this returns false
  );
  return (
    <View>
      <View>Hue: {dpState.colour_data?.hue}</View>
      <View>Saturation: {dpState.colour_data?.saturation}</View>
      <View>Value: {dpState.colour_data?.value}</View>
    </View>
  );
}
```
