# Остров в LiveView: сокет, хуки и события — Mercury LMS > LM1. Один LiveSocket на страницу; `MercuryHook` и его `mounted`/`updated`/`reconnected`/`destroyed`; свойства следуют за assigns LiveView через патчи; события на сервер через `pushEvent`, с сервера через `push_event` + `handleEvent`. ## Когда читать Когда вы связываете остров с его LiveView: открываете сокет, отправляете событие из острова, отвечаете на сервере или направляете серверное событие одному острову. ## Контракт - Пути сокетов: echd_os — `socket "/live"`; echo_edu — `socket "/_edu/live"`, загрузчик EDU читает его из `` (иначе `"/live"`). - Один LiveSocket на страницу: `new LiveSocket(path, Socket, { params: { _csrf_token }, hooks })`. Карта импортов направляет `@fiberfx/phoenix` и `@fiberfx/phoenix_live_view` на одну обслуживаемую копию каждого пакета. - `updated()`: `data-use-diff="true"` → `applyPatch(props, data-props-diff)`, иначе полные `data-props`; патчи потоков из `data-streams-diff`. `reconnected()`: полные `data-props`, потоки строятся заново из `{}`. `destroyed()`: `render(null)` и удаление каждой ссылки `handleEvent`, созданной через хук. - Каждое обновление создаёт новый объект свойств верхнего уровня; незатронутые вложенные значения сохраняют идентичность. - На сервере при включённом `diff` (по умолчанию) отправляются только assigns, помеченные LiveView как изменённые; ключ без старого значения → `replace /`, иначе `Jsonpatch.diff` под `/`. - Функции хука (свойства либо `useLiveMercury()`; вне острова `null`): `pushEvent(event, payload?, onReply?)`, `pushEventTo(phxTarget, event, payload?, onReply?)`, `handleEvent(event, cb)` → ссылка, `removeHandleEvent(ref)`, `upload(name, files)`, `uploadTo(target, name, files)`. - Серверные события EDU: одно имя, `"edu:island"` (`SERVER_EVENT`), сообщение `%{id, event, payload}`; фильтрация через `isAddressedTo(payload, islandId)` из `@echd/edu-boot/island`. - `Link`: `patch` → `data-phx-link="patch"`; `navigate` → `"redirect"` (та же `live_session`); `replace` → `data-phx-link-state="replace"`; только `href` → обычная ссылка. ## Минимальный пример ```tsx import { useEffect } from "@fiberfx/hyperscript/hooks"; import { useLiveMercury } from "@fiberfx/live-mercury"; import { isAddressedTo, SERVER_EVENT } from "@echd/edu-boot/island"; export function Ping(props: { islandId?: string }) { const live = useLiveMercury(); const handleEvent = live?.handleEvent; const removeHandleEvent = live?.removeHandleEvent; const islandId = props.islandId ?? ""; useEffect(() => { if (!handleEvent || !removeHandleEvent) return; const ref = handleEvent(SERVER_EVENT, (payload) => { if (isAddressedTo(payload, islandId)) console.log(payload.event, payload.payload); }); return () => removeHandleEvent(ref); }, [handleEvent, removeHandleEvent, islandId]); return ; } ``` ```elixir def handle_event("demo:clicked", %{"count" => count}, socket) do {:noreply, push_event(socket, "edu:island", %{id: "island-demo", event: "ack", payload: %{count: count}})} end ``` ## Не выдавать Второй `new LiveSocket(...)` на странице, где он уже есть; `phx-update` со значением, отличным от `"ignore"`, на острове; импорт из `react`. ## Дальше - LM2, сборка островов через mx: /ru/live-mercury/building (/ru/live-mercury/building/llms.txt) - Назад: /ru/live-mercury/islands/llms.txt - Эта текстовая версия: /ru/live-mercury/liveview/llms.txt ## Навигация - [Страница в браузере](/ru/live-mercury/liveview) - [Индекс для агентов](/ru/llms.txt) - [Все английские текстовые версии](/llms-full.txt) - [Карта сайта](/sitemap.xml) - [Текст курса](/ru/live-mercury/llms.txt)