Appearance
Embedding with React / Vue
Integrate Layota maps into your frontend framework using the JavaScript SDK.
React
Basic Component
tsx
import { useEffect, useRef } from 'react'
import { LayotaMap } from '@layota/map-sdk'
export function MapView({ projectId }: { projectId: string }) {
const containerRef = useRef<HTMLDivElement>(null)
const mapRef = useRef<LayotaMap | null>(null)
useEffect(() => {
if (!containerRef.current) return
const map = new LayotaMap({
container: containerRef.current,
projectId,
})
mapRef.current = map
map.ready().then(() => {
console.log('Map is ready')
})
return () => {
map.destroy()
}
}, [projectId])
return <div ref={containerRef} style={{ width: '100%', height: '600px' }} />
}With Events
tsx
import { useEffect, useRef, useCallback } from 'react'
import { LayotaMap, Area } from '@layota/map-sdk'
interface Props {
projectId: string
onAreaClick?: (area: Area) => void
}
export function MapView({ projectId, onAreaClick }: Props) {
const containerRef = useRef<HTMLDivElement>(null)
const mapRef = useRef<LayotaMap | null>(null)
useEffect(() => {
if (!containerRef.current) return
const map = new LayotaMap({
container: containerRef.current,
projectId,
})
mapRef.current = map
map.on('areaClick', (area) => {
onAreaClick?.(area)
})
return () => map.destroy()
}, [projectId])
const selectArea = useCallback((areaId: string) => {
mapRef.current?.selectArea(areaId).focusOn(areaId)
}, [])
return <div ref={containerRef} style={{ width: '100%', height: '600px' }} />
}Usage
tsx
function App() {
return (
<MapView
projectId="your-project-id"
onAreaClick={(area) => console.log('Clicked:', area.title)}
/>
)
}Vue 3
Basic Component
vue
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { LayotaMap } from '@layota/map-sdk'
const props = defineProps<{
projectId: string
}>()
const emit = defineEmits<{
areaClick: [area: { id: string; title: string }]
}>()
const container = ref<HTMLElement>()
let map: LayotaMap | null = null
onMounted(async () => {
if (!container.value) return
map = new LayotaMap({
container: container.value,
projectId: props.projectId,
})
map.on('areaClick', (area) => {
emit('areaClick', area)
})
await map.ready()
})
onUnmounted(() => {
map?.destroy()
})
function selectArea(areaId: string) {
map?.selectArea(areaId).focusOn(areaId)
}
defineExpose({ selectArea })
</script>
<template>
<div ref="container" style="width: 100%; height: 600px" />
</template>Usage
vue
<script setup lang="ts">
import MapView from './MapView.vue'
function handleAreaClick(area: { id: string; title: string }) {
console.log('Clicked:', area.title)
}
</script>
<template>
<MapView
project-id="your-project-id"
@area-click="handleAreaClick"
/>
</template>Key Points
- Always call
destroy()when the component unmounts to clean up the iframe and event listeners - One map per container — don't reuse the same DOM element for multiple maps
ready()is optional — you can subscribe to events before the map loads; they'll fire when ready- The SDK handles the iframe lifecycle — you just need a container element