useStructuredDevicesProps(selector: (structuredDevicesProps: { [key: string]: Record<string, any> }) => any;, equalityFn?: (prev: any, next: any) => boolean;)

Requires:
@ray-js/panel-sdk≥1.16.0
Before use, both of the following must be met:Read the full notes
Before use, both of the following must be met:
1. Mount SdmDevicesProvider and configure the associated device mapping
2. Each device has configured the dp-kit interceptor (createDpKit) during initialization
Performance optimization (best practices):
1. Strongly recommend always scoping the selector to the exact feature point, e.g., useStructuredDevicesProps(props => props.main?.colour_data), to avoid full subscriptions that cause unnecessary rerenders when unrelated devices or feature points change.
2. If the selector must return an object containing multiple fields, the default shallow comparison (shallow equal) ensures rerender will not be triggered as long as the extracted values do not change. If needed, pass a custom equalityFn for fine-grained control.

Description

Get the structured DP state of associated devices; requires the dp-kit interceptor

Parameters

ParameterTypeRequiredDescription
selector(structuredDevicesProps: { [key: string]: Record<string, any> }) => any;YesSelector function. Input: the collection of structured props for all associated devices. The key is the device identifier, and the value is the device’s structured DP data parsed by dp-kit
equalityFn(prev: any, next: any) => boolean;NoCustom comparison function; if it returns true, re-render is not triggered; default is shallow equal

Return Value

Type: any
Structured DP value matching the selector

Examples

Subscribe only to a specific state of a single device

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

export default function MainDeviceColour() {
  // Precisely select the main device's colour_data; re-render only when it changes
  const colourData = useStructuredDevicesProps(
    props => props.main?.colour_data
  );
  return <Text>H: {colourData?.h}, S: {colourData?.s}, V: {colourData?.v}</Text>;
}

Configure dp-kit and use structured state (full integration flow)

// ---- 1. Parser: Custom Transformer example (using colour_data as an example) ----
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. Configure dpKit and inject into 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();

// Inject dp-kit interceptors during batchAdd
deviceManager.batchAdd([
  { key: 'lamp1', deviceId: 'xxx_device_id_1', interceptors: dpKit.interceptors },
  { key: 'lamp2', deviceId: 'xxx_device_id_2', interceptors: dpKit.interceptors },
]);

// ---- 3. Page component consumes structured data ----
export default function ColourDataList() {
  // Recommended: select only the required state, e.g., 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>
  );
}

Custom rerender

// useStructuredDevicesProps has built-in shallow equality checks on the selector's return value; in typical cases, you don't need to pass 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>
  );
}