Async Handling One of Grunfeld's powerful features is the ability to naturally handle asynchronous operations. You can perform async operations when creating dialogs or display multiple dialogs sequentially.
Loading Dialog # You can create a dialog that displays loading state during async operations:
const loadData = async () => {
const promise = grunfeld.add<string>(async (removeWith) => {
// First, show loading UI
const loadingElement = (
<div style={{ padding: "20px", textAlign: "center" }}>
<p>Loading user information...</p>
<div>⏳</div>
</div>
);
// Perform async operation
try {
const data = await fetch("/api/user").then((r) => r.json());
// To update UI after successful load,
// you need to create a new dialog or use state management
removeWith(data);
} catch (error) {
// Close with error on failure
removeWith(null);
}
return loadingDialog;
});
const result = await promise;
console.log("Loaded data:", result);
};Sequential Dialogs # You can implement complex workflows by displaying multiple dialogs sequentially:
const runWorkflow = async () => {
// Step 1: Email input
const email = await grunfeld.add<string>((removeWith) => ({
element: <EmailInput onSubmit={removeWith} />,
}));
if (!email) return;
// Step 2: Password input
const password = await grunfeld.add<string>((removeWith) => ({
element: <PasswordInput email={email} onSubmit={removeWith} />,
}));
if (!password) return;
// Step 3: Confirmation
const confirmed = await grunfeld.add<boolean>((removeWith) => ({
element: (
<div>
<p>Do you want to sign up with this information?</p>
<p>Email: {email}</p>
<button onClick={() => removeWith(true)}>Sign Up</button>
<button onClick={() => removeWith(false)}>Cancel</button>
</div>
),
}));
if (confirmed) {
await signup(email, password);
}
};Timeout Handling # You can automatically close a dialog after a certain time and handle the Promise:
const showTimedDialog = async () => {
const dialogPromise = grunfeld.add<boolean>((removeWith) => ({
element: (
<div>
<p>Please respond within 10 seconds</p>
<button onClick={() => removeWith(true)}>Confirm</button>
<button onClick={() => removeWith(false)}>Cancel</button>
</div>
),
}));
// Auto-close after 10 seconds
const timeoutId = setTimeout(() => {
grunfeld.remove();
}, 10000);
const result = await dialogPromise;
clearTimeout(timeoutId);
if (result === undefined) {
console.log("Closed due to timeout");
} else if (result) {
console.log("User selected confirm");
} else {
console.log("User selected cancel");
}
};