---
name: "useStructuredDevicesProps"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.16.0" }
title: "useStructuredDevicesProps"
summary: "多设备管理 useStructuredDevicesProps Hook 说明，介绍如何结合 dp-kit 读取多台设备的结构化 DP 状态，并按需订阅特定功能点。"
---

## useStructuredDevicesProps

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

> 💡 使用前需同时满足：
> 1. 挂载 SdmDevicesProvider 并配置关联设备映射
> 2. 各设备初始化时已配置 dp-kit 拦截器（createDpKit）
> 性能优化（最佳实践）：
> 1. 强烈建议始终将 selector 的颗粒度精确到具体的功能点，例如 useStructuredDevicesProps(props => props.main?.colour_data)，避免全量订阅导致无关设备或无关功能点改变时引发无效的重渲染。
> 2. 如果 selector 必须返回包含多个字段的对象，由于默认使用浅比较（shallow equal），只要提取的值未发生改变就不会触发重渲染。必要时也可传入 equalityFn 进行深度定制。

### 描述

获取关联设备的结构化功能点状态，需配合 dp-kit 拦截器使用

### 参数

`Params`

| 参数 | 类型 | 必填 | 描述 |
| --- | --- | --- | --- |
| `selector` | `(structuredDevicesProps: { [key: string]: Record<string, any> }) => any;` | 是 | 选择器函数，入参为所有关联设备的结构化 props 集合。   key 为设备标识，value 为该设备经 dp-kit 解析后的结构化功能点数据 |
| `equalityFn` | `(prev: any, next: any) => boolean;` | 否 | 自定义比较函数，返回 true 则不触发重渲染，默认 shallow equal |

### 返回值

类型: `any`

匹配选择器的结构化功能点值

### 示例代码

#### 仅订阅单台设备的特定状态

```tsx
import { useStructuredDevicesProps } from '@ray-js/panel-sdk';

export default function MainDeviceColour() {
  // 精确选取 main 设备的 colour_data，仅在它改变时才重渲染
  const colourData = useStructuredDevicesProps(
    props => props.main?.colour_data
  );
  return <Text>H: {colourData?.h}, S: {colourData?.s}, V: {colourData?.v}</Text>;
}
```

#### 配置 dp-kit 并使用结构化状态（完整接入链路）

```tsx
// ---- 1. Parser：自定义 Transformer 示例（以 colour_data 为例） ----
type TColorData = { hue: number; saturation: number; value: number };
class ColourTransformer implements Transformer<TColorData> {
  defaultValue = { hue: 10, saturation: 1000, value: 1000 };
  uuid = 'colour_data';
  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. 配置 dpKit 并注入 SmartDevicesManager ----
import { createDpKit, SmartDevicesManager, useStructuredDevicesProps } from '@ray-js/panel-sdk';
import { lampSchemaMap } from '@/devices/schema';

const dpKit = createDpKit({
  protocols: {
    [lampSchemaMap.colour_data.code]: new ColourTransformer(),
  }
});
const deviceManager = new SmartDevicesManager();

// batchAdd 时注入 dp-kit 拦截器
deviceManager.batchAdd([
  { key: 'lamp1', deviceId: 'xxx_device_id_1', interceptors: dpKit.interceptors },
  { key: 'lamp2', deviceId: 'xxx_device_id_2', interceptors: dpKit.interceptors },
]);

// ---- 3. 页面组件消费结构化数据 ----
export default function ColourDataList() {
  // 推荐：精确选用需要的状态，例如 p => p.lamp1?.colour_data
  const structured = useStructuredDevicesProps(p => p);

  return (
    <View>
      {Object.keys(structured ?? {}).map(key => (
        <Text key={key}>
          {key} colour_data: hue={structured[key]?.colour_data?.hue}
        </Text>
      ))}
    </View>
  );
}
```

#### 自定义 rerender

```tsx
// useStructuredDevicesProps 内部已针对 selector 返回值做 shallow equal 浅比较，无特殊场景时无需传入 equalityFn。
import { useStructuredDevicesProps } from '@ray-js/panel-sdk';

export default function WorkModeMap() {
  const workModeMap = useStructuredDevicesProps(
    p => {
      const map: Record<string, string> = {};
      Object.keys(p ?? {}).forEach(k => { map[k] = p[k]?.work_mode; });
      return map;
    },
    (prev, next) => JSON.stringify(prev) === JSON.stringify(next)
  );

  return (
    <View>
      {Object.keys(workModeMap).map(k => (
        <Text key={k}>{k}: {workModeMap[k]}</Text>
      ))}
    </View>
  );
}
```
