# @dynatrace-sdk/react-hooks

The `@dynatrace-sdk/react-hooks` library provides a seamless way to interact with Dynatrace platform service clients in React applications. This package leverages hooks to greatly simplify the use of Dynatrace services within React. For detailed information, visit our [`Developer Portal`].

[`developer portal`]: https://dt-url.net/1s028x2

```bash
npm install @dynatrace-sdk/react-hooks
```

### Simplified data querying from Grail

Traditionally, querying data in Dynatrace involves using the client-query package and managing complex React state. The `useDql` hook in this package streamlines this process. The following example showcases how to fetch data with a DQL query:

```javascript
const { data, error, isLoading } = useDql('fetch logs');
```

This hook is fully compatible with the parameters used in the `queryExecute` function of the `@dynatrace-sdk/client-query` package.

For instance, to limit the number of results returned:

```javascript
const { data, error, isLoading, refetch } = useDql({
  query: 'fetch logs',
  maxResultRecords: 2000,
});
```

You can delay the execution of the query until a user clicks on a button by passing additional query options to the hook:

```javascript
const { data, error, isLoading, refetch } = useDql('fetch logs', { enabled: false });

function onClickQuery() {
  refetch();
}
```

You should add appropriate scopes to your app's configuration based on the query type. For more details, refer to the [Bucket and table permissions in Grail documentation](https://www.dynatrace.com/support/help/platform/grail/assign-permissions-in-grail).

### Fetching Grail fields

The `useGrailFields` hook fetches Grail fields from both autocomplete and DSS query sources and exposes them separately as `autocompleteData` and `dssData`. The `dataObject` accepts `"logs"`, `"spans"`, `"smartscape.nodes"`, or `"metrics"`.

```javascript
const { data, isLoading, isError, errors } = useGrailFields({
  autocompleteQueryOptions: { query: 'fetch logs' },
  dssQueryOptions: { dataObject: 'logs' },
});
```

Use `select` to transform the raw data before it's returned as `data`:

```javascript
const { data } = useGrailFields({
  autocompleteQueryOptions: { query: 'fetch logs' },
  dssQueryOptions: { dataObject: 'logs' },
  select: ({ autocompleteData }) =>
    autocompleteData?.suggestions?.map((s) => s.suggestion ?? '') ?? [],
});
```

### Interacting with documents and app states

Beyond DQL queries, our hooks facilitate interactions with documents and app state. They allow control over immediate or deferred query execution.

```javascript
const { data, error, isLoading } = useDocument({ id: documentId }, { autoFetch: true });
```

For creating, updating, or deleting documents or app state, an explicit execute call is necessary:

```javascript
const { data, execute, error } = useCreateDocument();

function onClickCreateDocument() {
  execute(DOCUMENT_DATA);
}
```

Depending on your interaction type, add these scopes to your app configuration:

| Function              | Scope                        |
| --------------------- | ---------------------------- |
| Document read         | document:documents:read      |
| Document write/update | document:documents:write     |
| Document delete       | document:documents:delete    |
| State read            | state:app-states:read        |
| State write           | state:app-states:write       |
| State delete          | state:app-states:delete      |
| User state read       | state:user-app-states:read   |
| User state write      | state:user-app-states:write  |
| User state delete     | state:user-app-states:delete |

### Interacting with Settings

Settings can be utilized in the following way:

```javascript
const { data, error, isLoading } = useSettingsV2(
  { schemaIds: SETTING_SCHEMA },
  { autoFetch: true },
);
```

For creating, updating, or deleting settings, an explicit execute call is necessary:

```javascript
const { data, execute, error } = useCreateSettingsV2();

function onClickCreateSettings() {
  execute(SETTING_DATA);
}
```

Depending on your interaction type, add these scopes to your app configuration:

| Function              | Scope                       |
| --------------------- | --------------------------- |
| Settings read         | app-settings:objects:read   |
| Settings write/update | app-settings:objects:write  |
| Settings delete       | app-settings:objects:delete |

### Simplified Use of Davis® Analyzers

Leveraging Davis® analyzers traditionally involves complex state management and polling logic, alongside the `@dynatrace-sdk/client-davis-analyzers` package. The `useAnalyzer` hook in this package makes this process much more straightforward:

```javascript
const { data, error, isLoading } = useAnalyzer({
  analyzerName: 'dt.statistics.GenericForecastAnalyzer',
  body: {
    timeSeriesData: {
      expression: query,
    },
  },
});
```

This hook supports all the parameters available in the executeAnalyzer method from the `@dynatrace-sdk/client-davis-analyzers` package.

To defer the execution of the analyzer until a user action, like a button click, configure the hook with additional options:

```javascript
const { data, error, isLoading, refetch } = useAnalyzer({
  analyzerName: 'dt.statistics.GenericForecastAnalyzer',
  body: {
    timeSeriesData: {
      expression: query,
    },
  },
  {
    autoFetch: false,
    autoFetchOnUpdate: true,
  }
});

function onExecuteAnalyzer() {
  refetch();
}
```

In your app's configuration, include the necessary scope:

| Function     | Scope                   |
| ------------ | ----------------------- |
| Use analyzer | davis:analyzers:execute |

### App functions

The useAppFunction hook is the simplest way to call app functions. As the other hooks in this package, it provides state handling for loading and error states:

```javascript
const { data, error, isLoading } = useAppFunction({ name: 'functionName', data: 'data' });
```

Sometimes you want to delay the execution of the app function until a user clicks on a button. This can be achieved by passing additional options to the hook:

```javascript
const { data, error, isLoading, refetch } = useAppFunction(
  { name: 'functionName', data: 'data' },
  { autoFetch: false, autoFetchOnUpdate: false },
);

function onClick() {
  refetch();
}
```
