Sometimes it may be necessary for your app to persist values. For example, if you were to build a "notes" app you may want to persist the items of the notes so that they can be recalled next time the app is loaded. We provide the state API for this purpose.
The state API exposes several methods via the SDK client. These are:
setState()
- set a state valuegetState()
- get a state valuedeleteState()
- delete a state value
There is also a set of methods for setting state against the current user. This may be useful for recording user-specific state values using the same name.
setUserState()
- set a state valuegetUserState()
- get a state valuedeleteUserState()
- delete a state value
Basic Usage
These state management methods are accessible from the apps SDK client, and a basic usage example is as follows:
import { SetStateResponse, GetStateResponse, useDeskproAppClient } from "@deskpro/app-sdk";
import { useEffect, useState } from "react";
export const MyComponent = () => {
const [notes, setNotes] = useState("");
const { client } = useDeskproAppClient();
// Load notes from state
useEffect(() => {
client?.getState<string>("notes")
.then((res: GetStateResponse<string>[]) => setNotes(res[0]?.data ?? ""))
;
}, [client]);
// Save notes to state
const save = () => {
client?.setState<string>("notes", notes)
.then((res: SetStateResponse) => console.log(res.isSuccess, res.errors))
;
};
return (
<>
<div>
<label htmlFor="notes">Notes:</label>
<textarea id="notes" onChange={(e) => setNotes(e.target.value)} value={notes} />
</div>
<div>
<button onClick={() => save()}>Save</button>
</div>
</>
);
}; copy
An important thing to note is that when getting values from state, the response always returns an array of values. This is because you can load collections of values via path name wildcards. For example, if we store the following values in state:
items/one
items/two
We can recall all of these values in one call using a wildcard like this:
client.getState<MyItem>("items/*")
.then((res: GetStateResponse<MyItem>[]) => console.log(res))
; copy
User Specific State
The problem with our notes app is that we're storing notes globally - so any Deskpro user can see them. This isn't great as we'd probably want to record notes for ourselves. Doing this is a simple change, instead of using *State()
methods, we use *UserState()
methods instead:
import { SetStateResponse, GetStateResponse, useDeskproAppClient } from "@deskpro/app-sdk";
import { useEffect, useState } from "react";
export const MyComponent = () => {
const [notes, setNotes] = useState("");
const { client } = useDeskproAppClient();
// Load notes from state
useEffect(() => {
client?.getUserState<string>("notes")
.then((res: GetStateResponse<string>[]) => setNotes(res[0]?.data ?? ""))
;
}, [client]);
// Save notes to state
const save = () => {
client?.setUserState<string>("notes", notes)
.then((res: SetStateResponse) => console.log(res.isSuccess, res.errors))
;
};
return (
<>
<div>
<label htmlFor="notes">Notes:</label>
<textarea id="notes" onChange={(e) => setNotes(e.target.value)} value={notes} />
</div>
<div>
<button onClick={() => save()}>Save</button>
</div>
</>
);
}; copy
Backend Only State
You can also store state that can be accessed by the backend only (apps proxy). To store backend only state values, you must pass the backend
flag option when storing state values like this:
client.setState<string>("secret_thing", "my secret value", {
backend: true,
}); copy
or, to set this as user-specific:
client.setUserState<string>("secret_thing", "my secret value", {
backend: true,
}); copy
You can then reference these values via placeholders in proxy requests. This works in a similar way to backend only settings, however the placeholder delimiters are slightly different. Here are some examples:
Backend only state:
[[secret_thing]] copy
User-specific backend only state:
[user[secret_thing]] copy
So, an example fetch URL might look like this (referencing a user-specific backend only state value):
https://example.com/api/users?key=[user[secret_thing]] copy
Please log in or register to submit a comment.