Destroys the playground instance and removes all event listeners.
After calling this method, any further SDK method calls will throw an error. This method is useful for cleaning up resources when the playground is no longer needed, such as when removing it from the page or navigating away.
Signature
playground.destroy(): Promise<void>
Parameters
None.
Returns
A promise that resolves when the playground has been destroyed. If called when already destroyed, the promise rejects with an error message.
Usage
Basic Usage
import { createPlayground } from "livecodes";
const playground = await createPlayground("#container");
// Use the playground...
await playground.run();
// Later, when done:
await playground.destroy();
// Playground is now destroyed
// Container is cleared
// Event listeners are removed
// This will throw an error:
// await playground.run(); // Error: Cannot call API methods after calling `destroy()`.
Clean Up on Page Navigation
import { createPlayground } from "livecodes";
let playground;
async function initPlayground() {
playground = await createPlayground("#container");
}
// Clean up when leaving the page
window.addEventListener('beforeunload', async () => {
if (playground) {
await playground.destroy();
}
});
Destroy and Recreate
import { createPlayground } from "livecodes";
let playground = await createPlayground("#container", {
config: {
markup: {
language: "html",
content: "<h1>Version 1</h1>",
},
},
});
// Later, completely reset the playground
const resetButton = document.getElementById('reset');
resetButton.addEventListener('click', async () => {
// Destroy the old playground
await playground.destroy();
// Create a fresh one
playground = await createPlayground("#container", {
config: {
markup: {
language: "html",
content: "<h1>Fresh Start</h1>",
},
},
});
});
Multiple Playgrounds
import { createPlayground } from "livecodes";
const playgrounds = [];
// Create multiple playgrounds
for (let i = 1; i <= 3; i++) {
const playground = await createPlayground(`#container${i}`);
playgrounds.push(playground);
}
// Later, destroy all playgrounds
async function cleanupAll() {
for (const playground of playgrounds) {
await playground.destroy();
}
playgrounds.length = 0; // Clear the array
}
// Call cleanup when needed
await cleanupAll();
Tab Navigation with Cleanup
import { createPlayground } from "livecodes";
const tabs = {
editor: null,
preview: null,
settings: null,
};
async function showTab(tabName) {
// Destroy current playground if exists
if (tabs[tabName]) {
await tabs[tabName].destroy();
}
// Create new playground for this tab
tabs[tabName] = await createPlayground(`#${tabName}-container`);
}
// Switch tabs
document.getElementById('editor-tab').addEventListener('click', () => {
showTab('editor');
});
document.getElementById('preview-tab').addEventListener('click', () => {
showTab('preview');
});
With Watch Cleanup
import { createPlayground } from "livecodes";
const playground = await createPlayground("#container");
// Set up watchers
const codeWatcher = playground.watch('code', ({ code }) => {
console.log('Code changed');
});
const consoleWatcher = playground.watch('console', ({ method, args }) => {
console[method](...args);
});
// Later, clean up everything
async function cleanup() {
// Remove watchers (optional - destroy() will handle this)
codeWatcher.remove();
consoleWatcher.remove();
// Destroy playground
await playground.destroy();
}
await cleanup();
Error Handling
import { createPlayground } from "livecodes";
const playground = await createPlayground("#container");
await playground.destroy();
// Attempting to use destroyed playground
try {
await playground.run();
} catch (error) {
console.error(error);
// Error: "Cannot call API methods after calling `destroy()`."
}
// Attempting to destroy again
try {
await playground.destroy();
} catch (error) {
console.error(error);
// Error: "Cannot call API methods after calling `destroy()`."
}
Watch Destroy Event
import { createPlayground } from "livecodes";
const playground = await createPlayground("#container");
// Watch for destruction
playground.watch('destroy', () => {
console.log('Playground destroyed!');
// Clean up any external resources
// Update UI state
document.getElementById('status').textContent = 'Playground destroyed';
});
// Later
await playground.destroy();
// "Playground destroyed!" is logged
Memory Leak Prevention
import { createPlayground } from "livecodes";
class PlaygroundManager {
constructor() {
this.playground = null;
}
async init(container) {
// Clean up old playground if exists
await this.cleanup();
// Create new playground
this.playground = await createPlayground(container);
}
async cleanup() {
if (this.playground) {
await this.playground.destroy();
this.playground = null;
}
}
}
const manager = new PlaygroundManager();
// Initialize
await manager.init('#container');
// Later, when component unmounts or page changes
await manager.cleanup();
React Component Example
import { createPlayground, type Playground } from "livecodes";
import { useEffect, useRef } from "react";
function PlaygroundComponent() {
const containerRef = useRef<HTMLDivElement>(null);
const playgroundRef = useRef<Playground | null>(null);
useEffect(() => {
let mounted = true;
async function init() {
if (containerRef.current) {
const playground = await createPlayground(containerRef.current);
if (mounted) {
playgroundRef.current = playground;
} else {
// Component unmounted during creation, clean up
await playground.destroy();
}
}
}
init();
// Cleanup on unmount
return () => {
mounted = false;
if (playgroundRef.current) {
playgroundRef.current.destroy();
}
};
}, []);
return <div ref={containerRef} />;
}
What Gets Cleaned Up
When destroy() is called, the following cleanup occurs:
- iframe removal - The playground iframe is removed from the DOM
- Event listeners - All message event listeners are removed
- Watchers - All watch callbacks are cleared
- Observers - Intersection observers (for lazy loading) are disconnected
- State - Internal state is marked as destroyed
Notes
- After calling
destroy(), the playground object cannot be reused. You must create a new playground instance.
- All watchers are automatically removed when the playground is destroyed.
- The container element remains in the DOM but is emptied of the playground content.
- Calling
destroy() multiple times will result in an error.
- This method should be called when:
- Removing the playground from the page
- Navigating away from a single-page application route
- Switching between different playground configurations
- Preventing memory leaks in long-running applications
watch() - Watch for the "destroy" event
- All SDK methods will throw an error after
destroy() is called