Skip to main content

useDataQuery Hook

Declaratively define data dependencies and respond to loading / error / data state changes.

Basic Usage:

import { useDataQuery } from '@dhis2/app-runtime'

// Within a functional component body
const { loading, error, data, refetch } = useDataQuery(query, options)

Input

NameTypeRequiredDescription
queryQueryrequiredThe Query definition describing the requested data
optionsObjectAn optional set of query options
options.variablesObjectVariables to be passed to the dynamic portions of the query (can also be passed via the refetch function, see Output below)
options.onCompleteFunctionCallback function to be called on successfull completion of the query. Called with the response data as the only argument.
options.onErrorFunctionCallback function to be called on failure of the query. Called with the error instance as the only argument.
options.lazybooleanIf true, wait until refetch is called before fetching data.
Default: false

Output

NameTypeDescription
calledbooleantrue if the data request has been initiated with either lazy: false or refetch() at least once
loadingbooleantrue if the data is not yet available and no error has yet been encountered
errorError
or
undefined
undefined if no error has occurred, otherwise the Error which was thrown
dataQueryResult
or
undefined
undefined if the data is loading or an error has occurred, otherwise a map from the name of each QueryDefinition defined in the Query to the resulting data for that query
refetchFunctionThis function can be called to refetch the data and can accept variables (see Examples below). Any in-flight HTTP requests will automatically be aborted.
engineData EngineA reference to the DataEngine instance

Examples

Static query

This is a minimal example showing how to fetch the first page of indicators with a descending order.

import React from 'react'
import { useDataQuery } from '@dhis2/app-runtime'
import { CircularLoader } from '@dhis2/ui'

const PAGE_SIZE = 10
const query = {
indicators: {
resource: 'indicators.json',
params: {
order: 'shortName:desc',
pageSize: PAGE_SIZE,
},
},
}
export const IndicatorList = () => {
const { loading, error, data } = useDataQuery(query)
return (
<div>
<h3>Indicators (first 10)</h3>
{loading && <CircularLoader />}
{error && <span>{`ERROR: ${error.message}`}</span>}
{data && (
<pre>
{data.indicators.indicators
.map((ind) => ind.displayName)
.join('\n')}
</pre>
)}
</div>
)
}

Dynamic Query

This example is similar to the previous one but builds on top of it by showing how to fetch new pages of data using dynamic variables. A similar approach can be used implement dynamic filtering, ordering, etc.

import React from 'react'
import { useDataQuery } from '@dhis2/app-runtime'
import { Pagination, CircularLoader } from '@dhis2/ui'

const PAGE_SIZE = 10
const query = {
// "page" variable below can be dinamically passed via refetch (see "handlePageChange" below)
indicators: {
resource: 'indicators.json',
params: ({ page }) => ({
order: 'shortName:desc',
pageSize: PAGE_SIZE,
page,
}),
},
}

export const IndicatorList = () => {
const { loading, error, data, refetch } = useDataQuery(query)

const pager = data?.indicators?.pager
const hasNextPage = pager?.nextPage

const handlePageChange = (nextPage) => {
// "page" variable in query is passed via refetch below
refetch({ page: nextPage })
}

return (
<div>
<h3>Indicators (paginated)</h3>
{loading && <CircularLoader />}
{error && <span>{`ERROR: ${error.message}`}</span>}
{data && (
<pre>
{data.indicators.indicators
.map((ind) => ind.displayName)
.join('\n')}
</pre>
)}

{pager && (
<Pagination
page={pager.page}
pageCount={pager.pageCount}
pageSize={PAGE_SIZE}
total={pager.total}
isLastPage={hasNextPage}
onPageChange={handlePageChange}
hidePageSizeSelect={true}
/>
)}
</div>
)
}