ChemPal Documentation - v1.7.0
    Preparing search index...

    Function useOptimisticResultsWithPending

    • Extended optimistic-results hook that tracks a per-item pending state. Each product passes through three lifecycle stages: add (pending) → confirm (persisted) or error (removed). This lets the UI render a loading indicator on rows that are not yet confirmed.

      Parameters

      • confirmedResults: Product[]

        The server-confirmed product list (source of truth)

      Returns {
          results: (
              | Product
              | {
                  _id: number;
                  isPending: boolean;
                  shortDescription?: string;
                  rating?: number;
                  reviewCount?: number;
                  baseQuantity?: number;
                  baseUom?: Uom;
                  usdPrice?: number;
                  localPrice?: number;
                  sku?: string
                  | number;
                  id?: string | number;
                  uuid?: string | number;
                  cacheKey?: string;
                  grade?: string;
                  concentration?: string;
                  moleweight?: number;
                  formula?: string;
                  purity?: string;
                  status?: string;
                  statusTxt?: string;
                  shippingInformation?: string;
                  purchaseRestriction?: PurchaseRestriction;
                  availability?: Availability;
                  attributes?: { name: string; value: string }[];
                  moles?: number;
                  images?: ProductImage[];
                  parentProduct?: { title: string; url: string; permalink?: string };
                  priceSeriesKey?: string;
                  priceTrendValue?: number;
                  supplier: string;
                  title: string;
                  url: string;
                  permalink?: string;
                  price: number;
                  currencyCode: valueof;
                  currencySymbol: valueof;
                  quantity: number;
                  uom: string;
                  description?: string;
                  manufacturer?: string;
                  cas?: `${string}-${string}-${string}`;
                  vendor?: string;
                  variants?: Variant[];
                  docLinks?: string[];
                  sdsUrl?: string;
                  coaUrl?: string;
                  specSheetUrl?: string;
                  supplierCountry?: any;
                  supplierShipping?: ShippingRange;
                  paymentMethods?: PaymentMethod[];
                  supplierEbayStoreURL?: string;
                  supplierAmazonStoreURL?: string;
                  _fuzz?: { score: number; idx: number };
                  matchPercentage?: number;
                  smiles?: undefined;
                  iupacName?: IupacName<string>;
                  pubchemId?: PubChemCID;
                  inchiKey?: InChIKey<string>;
                  inchi?: InChI<string>;
              }
          )[];
          addPendingResult: (product: Product) => void;
          confirmResult: (product: Product) => void;
          removeFailedResult: (product: Product) => void;
      }

      An object with results, addPendingResult, confirmResult, and removeFailedResult functions.

      • results: (
            | Product
            | {
                _id: number;
                isPending: boolean;
                shortDescription?: string;
                rating?: number;
                reviewCount?: number;
                baseQuantity?: number;
                baseUom?: Uom;
                usdPrice?: number;
                localPrice?: number;
                sku?: string
                | number;
                id?: string | number;
                uuid?: string | number;
                cacheKey?: string;
                grade?: string;
                concentration?: string;
                moleweight?: number;
                formula?: string;
                purity?: string;
                status?: string;
                statusTxt?: string;
                shippingInformation?: string;
                purchaseRestriction?: PurchaseRestriction;
                availability?: Availability;
                attributes?: { name: string; value: string }[];
                moles?: number;
                images?: ProductImage[];
                parentProduct?: { title: string; url: string; permalink?: string };
                priceSeriesKey?: string;
                priceTrendValue?: number;
                supplier: string;
                title: string;
                url: string;
                permalink?: string;
                price: number;
                currencyCode: valueof;
                currencySymbol: valueof;
                quantity: number;
                uom: string;
                description?: string;
                manufacturer?: string;
                cas?: `${string}-${string}-${string}`;
                vendor?: string;
                variants?: Variant[];
                docLinks?: string[];
                sdsUrl?: string;
                coaUrl?: string;
                specSheetUrl?: string;
                supplierCountry?: any;
                supplierShipping?: ShippingRange;
                paymentMethods?: PaymentMethod[];
                supplierEbayStoreURL?: string;
                supplierAmazonStoreURL?: string;
                _fuzz?: { score: number; idx: number };
                matchPercentage?: number;
                smiles?: undefined;
                iupacName?: IupacName<string>;
                pubchemId?: PubChemCID;
                inchiKey?: InChIKey<string>;
                inchi?: InChI<string>;
            }
        )[]
      • addPendingResult: (product: Product) => void
      • confirmResult: (product: Product) => void
      • removeFailedResult: (product: Product) => void
      const { results, addPendingResult, confirmResult, removeFailedResult } =
      useOptimisticResultsWithPending(searchResults);

      addPendingResult(product); // row appears with isPending: true
      confirmResult(product); // isPending flips to false
      removeFailedResult(product); // row is removed from the list
      export function useOptimisticResultsWithPending(confirmedResults: Product[]) {
      const [optimisticResults, addOptimisticResult] = useOptimistic(
      confirmedResults,
      (
      state: Product[],
      action: { type: 'add' | 'confirm' | 'error'; product: Product; tempId?: string },
      ) => {
      switch (action.type) {
      case 'add':
      // `_id` positions the row; confirm/error match on that same positional key.
      return [...state, { ...action.product, _id: state.length, isPending: true }];

      case 'confirm':
      return state.map((item) =>
      item._id === action.product._id ? { ...action.product, isPending: false } : item,
      );

      case 'error':
      return state.filter((item) => item._id !== action.product._id);

      default:
      return state;
      }
      },
      );

      /**
      * Add a product in the pending state (`isPending: true`).
      * @param product - The product to insert optimistically
      * @source
      */
      const addPendingResult = (product: Product) => {
      addOptimisticResult({ type: 'add', product });
      };

      /**
      * Mark a previously pending product as confirmed (`isPending: false`).
      * @param product - The confirmed product (must have a matching `_id`)
      * @source
      */
      const confirmResult = (product: Product) => {
      addOptimisticResult({ type: 'confirm', product });
      };

      /**
      * Remove a product that failed processing from the optimistic list.
      * @param product - The failed product (must have a matching `_id`)
      * @source
      */
      const removeFailedResult = (product: Product) => {
      addOptimisticResult({ type: 'error', product });
      };

      return {
      results: optimisticResults,
      addPendingResult,
      confirmResult,
      removeFailedResult,
      };
      }