Skip to main content

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 { Page, Button } from '@dynatrace/strato-components-preview';

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

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 { Page, Button, List, Text } from '@dynatrace/strato-components-preview';

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

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, Checkbox } from '@dynatrace/strato-components-preview';

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

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 { Page, Button } from '@dynatrace/strato-components-preview';

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

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 { Page, Button } from '@dynatrace/strato-components-preview';

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

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.

Still have questions?
Find answers in the Dynatrace Community