How to initialize the BBG Market Data API as a singleton in React

  1. Update @glue42/bbg-market-data to the latest version.

  2. Initialize the BBGMarketData instance only once in your application. For example, in the entry file when you initialize the IO instance.

E.g.:

import IODesktopFactory from '@interopio/desktop';
import BBGMarketDataFactory from '@glue42/bbg-market-data';
  
IODesktopFactory()
  .then((io) => {
    window.io = io;    
    if (!window.bbgMarketData) {
      window.bbgMarketData = BBGMarketDataFactory(io.interop);
    }

    
    console.log('IO instance is ready');
    console.log('BBG Market Data instance is ready');
  });
  1. Opening and closing requests are asynchronous operations and this behavior should be handled properly. Here is a suggested approach for your useReferenceData hook:
import { useEffect, useState } from 'react';

import {
    BBGMarketDataAPI,
    ReferenceData,
    ReferenceDataRequest,
    ReferenceDataRequestArguments
} from '@glue42/bbg-market-data';

export function useReferenceData(ticker: string): { data: ReferenceData; } {
    const [data, setData] = useState<ReferenceData>([]);

    useEffect(() => {
        setData([]);
    }, [ticker]);

    useEffect(() => {
        if (!ticker) {
            return;
        }

        // Note: Use local state to track if the component is unmounted.
        let unmounted = false;

        const requestArgs: ReferenceDataRequestArguments = {
            securities: [ticker],
            fields: []
            // ...otherArgs 
        };

        const request: ReferenceDataRequest = ((window as never as any).bbgMarketData as BBGMarketDataAPI).createReferenceDataRequest(requestArgs);

        (async () => {
            try {
                const result = await request.open({ aggregateResponse: true });
                // Note: There is not need to close the request when the operation completes. The library will do it automatically.

                // Note: Prevent stale state updates.
                if (unmounted) {
                    return;
                }

                setData(result as never as ReferenceData);
            } catch (error) {
                // Note: Handle errors appropriately. The operation potentially can fail.

                console.error(`Failed to get ref data for ticker ${ticker}.`, error);
            }
        })();


        return () => {
            // Note: Set the unmounted flag to true to prevent state updates after unmounting.
            unmounted = true;

            console.log(`Unmounting for ticker ${ticker}...`);
            console.log(`Closing ref data for ticker ${ticker}...`);

            // Note: Close the request to clean up resources **when** the ticker changes or the component unmounts.
            request.close()
                .then(() => {
                    console.log(`Closed ref data request for ticker ${ticker}.`);
                })
                .catch((error) => {
                    console.error(`Failed to close the BBGMarketData request for ticker ${ticker}.`, error);
                });
        };

    }, [ticker]);

    return { data };
} 

Mind the notes in the code above. They are guidelines to consider.