Store user-generated data
If your app allows the user to save user-generated data that needs to be available across multiple user sessions, our document service is your best option. One example of such user-defined data is to-do items that the user enters in a Todo app. This guide explains how you can store, update, and delete data from the document service.
The @dynatrace-sdk/react-hooks
package provides hooks that allow you to do all these operations.
Create document
To create a document, use the useCreateDocument
hook. This hook provides an execute
function that you can use to create a new document. It also provides some additional fields with information about the loading status, errors, and the response. These fields are common to all the document hooks. The example below shows how to create a Todo list document:
import React from 'react';
import { useCreateDocument } from '@dynatrace-sdk/react-hooks';
import { Button } from '@dynatrace/strato-components/buttons';
import { Page } from '@dynatrace/strato-components-preview/layouts';
const todos = [
{
title: 'Send email to John about vacation',
done: false,
},
{
title: 'Plan workshop for next week',
done: false,
},
];
const App = () => {
const { execute, data, error, isLoading } = useCreateDocument();
const handleClick = () => {
execute({
body: {
name: 'My Todos',
type: 'TodoList',
content: new Blob([JSON.stringify(todos)], {
type: 'application/json',
}),
},
});
};
return (
<Page>
<Button onClick={handleClick}>Create Todos</Button>
</Page>
);
};
This operation requires the scope document:documents:write
. Read more about scopes in this guide.
List documents
The useListDocuments
hook lets you to get a filtered list of the available documents. Besides the common fields, this hook also provides a refetch
function to refetch the list of documents. The following code fetches the documents of type TodoList.
import React from 'react';
import { useListDocuments } from '@dynatrace-sdk/react-hooks';
import { Button } from '@dynatrace/strato-components/buttons';
import { List, Text } from '@dynatrace/strato-components/typography';
import { Page } from '@dynatrace/strato-components-preview/layouts';
const App = () => {
const { data, refetch } = useListDocuments({
filter: `type == 'TodoList'`,
});
const handleClick = () => {
refetch().then((list) => console.log(list.documents));
};
return (
<Page>
{data && (
<List>
{data.documents.map((doc) => (
<Text key={doc.id}>{doc.name}</Text>
))}
</List>
)}
<Button onClick={handleClick}>Refetch Todos</Button>
</Page>
);
};
This operation requires the scope document:documents:read
. Read more about scopes in this guide.
Get document content
To retrieve the content of a specific document, you can use the useDownloadDocument
hook. This hook expects the document ID as a parameter and returns binary data with the document's contents, which you can extract by calling the get
function. This example shows how to fetch the content for the Todo list document that we created in the first step:
import React, { useState, useEffect } from 'react';
import { useDownloadDocument } from '@dynatrace-sdk/react-hooks';
import { Page } from '@dynatrace/strato-components-preview/layouts';
import { Checkbox } from '@dynatrace/strato-components-preview/forms';
interface Todo {
title: string;
done: boolean;
}
const App = () => {
const [todos, setTodos] = useState<Todo[]>();
const { data } = useDownloadDocument({
id: 'ff96e29d-2622-48f0-8c88-b2f20b2cf532',
});
useEffect(() => {
if (data) {
data.get('json').then((todos) => {
setTodos(todos);
});
}
}, [data]);
return (
<Page>
{todos &&
todos.map((todo) => (
<Checkbox key={todo.title} name="done" defaultValue={todo.done}>
{todo.title}
</Checkbox>
))}
</Page>
);
};
This operation requires the scope document:documents:read
. Read more about scopes in this guide.
Update document
Whenever you need to change the contents of a document, use the useUpdateDocument
or the useUpdateDocumentMetadata
hooks.
For all modifying operations, keep optimistic locking in mind. Every document has a version that's incremented whenever its metadata or content is modified. For every modifying operation, you have to pass this exact version, which you can retrieve with the useDocumentMetadata
hook. It could look like the following:
import React from 'react';
import { useDocumentMetaData, useUpdateDocument } from '@dynatrace-sdk/react-hooks';
import { Button } from '@dynatrace/strato-components/buttons';
import { Page } from '@dynatrace/strato-components-preview/layouts';
const updatedTodos = [
{
title: 'Send e-mail to John concerning vacation',
done: true,
},
{
title: 'Plan workshop for next week',
done: false,
},
];
const App = () => {
const metadata = useDocumentMetaData({
id: 'ff96e29d-2622-48f0-8c88-b2f20b2cf532',
});
const { execute } = useUpdateDocument();
const handleClick = () => {
if (metadata.data) {
execute({
id: metadata.data.id,
optimisticLockingVersion: metadata.data.version,
body: {
content: new Blob([JSON.stringify(updatedTodos)], {
type: 'application/json',
}),
},
});
}
};
return (
<Page>
<Button onClick={handleClick}>Update Todos</Button>
</Page>
);
};
This operation requires the scope document:documents:write
. Read more about scopes in this guide.
Delete document
You can delete documents as well. To do so, use the useDeleteDocument
hook. To delete a document, you need to provide the optimistic locking version of the document you want to delete.
To delete the document we created in the first step, your code should look like this:
import React from 'react';
import { useDocumentMetaData, useDeleteDocument } from '@dynatrace-sdk/react-hooks';
import { Button } from '@dynatrace/strato-components/buttons';
import { Page } from '@dynatrace/strato-components-preview/layouts';
const App = () => {
const metadata = useDocumentMetaData({
id: 'ff96e29d-2622-48f0-8c88-b2f20b2cf532',
});
const { execute } = useDeleteDocument();
const handleClick = () => {
if (metadata.data) {
execute({
id: metadata.data.id,
optimisticLockingVersion: metadata.data.version,
});
}
};
return (
<Page>
<Button onClick={handleClick}>Delete Todos</Button>
</Page>
);
};
This operation requires the scope document:documents:delete
. Read more about scopes in this guide.
Other uses
Since the hooks above are tied to React, you can't use them outside Dynatrace apps. If you need to access the documents service from an ad-hoc or app function, you need to use the documents client. Learn more about this on the @dynatrace-sdk/client-document reference page.