0

I am new to typescript and I am working on a project where I need to populate all the fields in GridModel interface by querying data. I have the below code after several attempt which works fine. In the below code, I pick single id from ids array and then make the necessary call to get all those fields and populate GridModel interface. Below code only works for single id which I pick as first index from ids array.

import { useEffect, useMemo, useState } from 'react'
import {
  useGetClientOrdersByItemQuery,
  useGetClientOrdersQuery,
  useGetClientOrderLineByLineIdLazyQuery,
} from '../../../../hooks/static/use-get-client-orders-by-item'

interface GridModel {
  purchaseOrderId: string | undefined,
  lineNumber: string | undefined,
  warehouse: string | undefined,
  startShipDate: string | undefined,
}

export const useViewPurchaseOrderData = (ids: string[]) => {
  const [gridData, setGridData] = useState<GridModel[]>([])
  const [fetchLines, { loading: linesLoading }] = useGetClientOrderLineByLineIdLazyQuery()
  const { data, loading } = useGetClientOrdersByItemQuery({
    variables: { itemId: Number(ids[0]) },
    skip: !ids[0],
  })

  const poIds = (data?.getPurchaseOrdersByItem?.map((p) => p?.purchaseOrderId)
    .filter((poid): poid is number => Boolean(poid)) ?? [])
  const poidToLines = useMemo(() => data?.getPurchaseOrdersByItem
    ?.map((p) => ({ orderId: p?.purchaseOrderId, lines: p?.lineIds })), [data])

  const { data: purchaseData, loading: purchaseLoading } = useGetClientOrdersQuery({
    variables: { poIds, count: poIds.length, offset: 0 },
    skip: !poIds.length,
  })
  const purchaseOrders = purchaseData?.getPurchaseOrders?.purchaseOrders

  useEffect(() => {
    const lineRequests = poidToLines?.flatMap((p) => p?.lines?.map((lineId) => fetchLines({
      variables: {
        purchaseOrderId: p?.orderId ?? 0,
        purchaseOrderLineId: lineId ?? 0,
      },
    }).then((result) => ({
      result: result.data?.getPurchaseOrderLineByLineId,
      poId: p?.orderId,
    })))).filter(Boolean) as Promise<any>[]

    if (purchaseOrders && purchaseOrders.length && lineRequests && lineRequests.length) {
      Promise.all(lineRequests).then((lines) => {
        const mapped: GridModel[] = lines.map((line) => {
          const order = purchaseOrders.find((po) => po?.id === line.poId.toString())
          return {
            purchaseOrderId: order?.id ?? undefined,
            lineNumber: line?.result.lineId ?? undefined,
            warehouse: order?.site?.name ?? undefined,
            startShipDate: order?.expectedShipDate ?? undefined,
          }
        }) ?? []
        setGridData(mapped)
      })
    }
  }, [poidToLines, purchaseOrders])

  return {
    data: gridData,
    loading: loading || purchaseLoading || linesLoading,
  }
}

Problem Statement

Is there any way where I can loop around all ids in ids array either asynchronously or sequentially inside useViewPurchaseOrderData function? And for each single id, I will do exact same thing which I am already doing in above code? So idea is -

  • Iterate all id from ids array either asynchronously or sequentially. For each id do exact above thing and then once we have data for all id return everything back.

Is this possible to do by any chance in typescript. I am from Java, C# background so having hard time figuring out on how to do this in Typescript.

10
  • It seems the problem is with useGetClientOrdersByItemQuery accepting only a single id. The problem is less to do with typescript and more than you cannot loop hook calls in Reactjs. Can you show us the code of use-get-client-orders-by-item? Commented Dec 8, 2022 at 10:56
  • Here is the code for that. I have a graphql query which is what it is making these calls into. I generate the ref pastebin code by running npm run codegen after adding my graphql query. @Bergi Commented Dec 8, 2022 at 17:50
  • @Bergi So you are saying, I cannot do for each loop here in my above code in the question and run each id in parallel? Commented Dec 8, 2022 at 17:51
  • You cannot put a loop around the useGetClientOrdersByItemQuery() call, at least. See github.com/apollographql/apollo-feature-requests/issues/178 stackoverflow.com/q/59938677/1048572 stackoverflow.com/q/68281221/1048572 for possible approaches. The ideal solution would obviously exposing an API that accepts an array of ids. Commented Dec 8, 2022 at 17:57
  • When you say ideal solution - you mean having a graphql query that accepts an array of ids right so that it works as it is without looping around it. @Bergi Commented Dec 8, 2022 at 18:07

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.