Skip to main content

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

//...
}