import { useEffect, useRef } from "react"; interface TelegramUser { id: number; first_name?: string; last_name?: string; username?: string; photo_url?: string; auth_date: number; hash: string; } declare global { interface Window { __fsTelegramAuth?: (user: TelegramUser) => void; } } /** * Официальный Telegram Login Widget. Требует бота (@BotFather) и /setdomain * на текущий HTTPS-домен. botUsername — без «@». */ export function TelegramLoginButton({ botUsername, onAuth, }: { botUsername: string; onAuth: (user: TelegramUser) => void; }) { const ref = useRef(null); // onAuth держим в ref, чтобы он НЕ был в зависимостях эффекта: иначе новая инлайн- // функция на каждый рендер пересоздавала бы виджет (а cleanup сносит его innerHTML // в момент отрисовки — в dev со StrictMode кнопка из-за этого не появлялась). const onAuthRef = useRef(onAuth); onAuthRef.current = onAuth; useEffect(() => { window.__fsTelegramAuth = (user) => onAuthRef.current(user); const node = ref.current; if (!node) return; node.innerHTML = ""; // на случай повторного монтирования (StrictMode) const script = document.createElement("script"); script.src = "https://telegram.org/js/telegram-widget.js?22"; script.async = true; script.setAttribute("data-telegram-login", botUsername); script.setAttribute("data-size", "large"); script.setAttribute("data-userpic", "false"); script.setAttribute("data-request-access", "write"); script.setAttribute("data-onauth", "__fsTelegramAuth(user)"); node.appendChild(script); return () => { node.innerHTML = ""; }; }, [botUsername]); // только смена бота пересоздаёт виджет return
; }