Device SupportGroup Support

useStructuredProps(selector?: (structuredProps: object) => any, equalityFn?: (prev: any, next: any) => boolean)

Requires:
@ray-js/panel-sdk≥1.10.0
Additional notesRead the full notes
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. For new projects, you can develop directly based on the public-sdm example.
Before using, also make sure the dp-kit interceptor is configured; see 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

ParameterTypeRequiredDescription
selector(structuredProps: object) => anyNoSelector 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) => booleanNoCustom 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)

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

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>
  );
}