useFhirSearch
Return a Query for a search request.
Basic usage
import { asError } from "@bonfhir/core/r4b";
import { useFhirSearch } from "@bonfhir/query/r4b";
import { FhirValue } from "@bonfhir/react/r4b";
import { List } from "@mantine/core";
export default function MyComponent() {
  const patientsSearchQuery = useFhirSearch("Patient", (search) =>
    search
      ._include("Patient", "organization")
      ._sort("-_lastUpdated")
      ._count(20)
      ._total("accurate"),
  );
  if (patientsSearchQuery.isLoading) {
    return <div>Loading...</div>;
  }
  if (patientsSearchQuery.isError) {
    return <div>{asError(patientsSearchQuery.error)?.message}</div>;
  }
  return (
    <List>
      {patientsSearchQuery.data?.searchMatch().map((patient) => {
        return (
          <List.Item key={patient.id}>
            <FhirValue type="HumanName" value={patient.name} /> -
            <FhirValue
              type="string"
              value={patient.managingOrganization?.included()?.name}
            />
          </List.Item>
        );
      })}
    </List>
  );
}
See the Core documentation around search for more information about the search or the bundle navigator.
With the <FhirQueryLoader />
import { useFhirSearch } from "@bonfhir/query/r4b";
import { FhirQueryLoader, FhirValue } from "@bonfhir/react/r4b";
import { List } from "@mantine/core";
export default function MyComponent() {
  const patientsSearchQuery = useFhirSearch("Patient", (search) =>
    search
      ._include("Patient", "organization")
      ._sort("-_lastUpdated")
      ._count(20)
      ._total("accurate"),
  );
  return (
    <FhirQueryLoader query={patientsSearchQuery}>
      {(result) => (
        <List>
          {result.searchMatch().map((patient) => {
            return (
              <List.Item key={patient.id}>
                <FhirValue type="HumanName" value={patient.name} /> -
                <FhirValue
                  type="string"
                  value={patient.managingOrganization?.included()?.name}
                />
              </List.Item>
            );
          })}
        </List>
      )}
    </FhirQueryLoader>
  );
}
With pagination
The third argument of useFhirSearch is there to handle subsequent pages.
Since there is a direct depency between the search result and the url for the next page, you need to handle it through
a state change somehow. Ex:
import { useFhirSearch } from "@bonfhir/query/r4b";
import { FhirQueryLoader, FhirValue } from "@bonfhir/react/r4b";
import { Button, List, Stack } from "@mantine/core";
import { useState } from "react";
export default function MyComponent() {
  const [pageUrl, setPageUrl] = useState<string | undefined>(undefined);
  const patientsSearchQuery = useFhirSearch(
    "Patient",
    (search) =>
      search
        ._include("Patient", "organization")
        ._sort("-_lastUpdated")
        ._count(20)
        ._total("accurate"),
    // Notice how we pass the "next" page url here as a third argument
    // When it is falsy, it uses the search defined above.
    pageUrl,
  );
  return (
    <FhirQueryLoader query={patientsSearchQuery}>
      {(result) => (
        <Stack>
          <List>
            {result.searchMatch().map((patient) => {
              return (
                <List.Item key={patient.id}>
                  <FhirValue type="HumanName" value={patient.name} /> -
                  <FhirValue
                    type="string"
                    value={patient.managingOrganization?.included()?.name}
                  />
                </List.Item>
              );
            })}
          </List>
          {result.linkUrl("next") && (
            // Here we set the pageUrl using the bundle next link.
            <Button onClick={() => setPageUrl(result.linkUrl("next"))}>
              Go to next page - {result.total} total result(s)
            </Button>
          )}
        </Stack>
      )}
    </FhirQueryLoader>
  );
}
This is a simple example. You might be interested in leveraging the <FhirPagination /> components
and useFhirSearchController hook for this:
import { useFhirSearch } from "@bonfhir/query/r4b";
import {
  FhirPagination,
  FhirQueryLoader,
  FhirValue,
  useFhirSearchController,
} from "@bonfhir/react/r4b";
import { List, Stack } from "@mantine/core";
export default function MyComponent() {
  const searchController = useFhirSearchController({
    defaultSort: "-_lastUpdated",
    pageSize: 20,
  });
  const patientsSearchQuery = useFhirSearch(
    "Patient",
    (search) =>
      search
        ._include("Patient", "organization")
        ._sort(searchController.sort)
        ._count(searchController.pageSize)
        ._total("accurate"),
    searchController.pageUrl,
  );
  return (
    <FhirQueryLoader query={patientsSearchQuery}>
      {(result) => (
        <Stack>
          <List>
            {result.searchMatch().map((patient) => {
              return (
                <List.Item key={patient.id}>
                  <FhirValue type="HumanName" value={patient.name} /> -
                  <FhirValue
                    type="string"
                    value={patient.managingOrganization?.included()?.name}
                  />
                </List.Item>
              );
            })}
          </List>
          <FhirPagination {...patientsSearchQuery} {...searchController} />
        </Stack>
      )}
    </FhirQueryLoader>
  );
}
With options
import { DEFAULT_FHIR_CLIENT, useFhirSearch } from "@bonfhir/query/r4b";
export default function MyComponent() {
  const patientQuery = useFhirSearch(
    "Patient",
    (search) =>
      search
        ._include("Patient", "organization")
        ._sort("-_lastUpdated")
        ._count(20)
        ._total("accurate"),
    undefined,
    {
      // FHIR API options - matches the `FhirClient` options
      fhir: {
        _pretty: "true",
      },
      // The name of the FhirClient to use
      fhirClient: DEFAULT_FHIR_CLIENT,
      // React query options
      query: {
        gcTime: Number.POSITIVE_INFINITY,
      },
    },
  );
  //...
}