fix: refactor Altcha component to properly handle custom element registration and attribute setting

This commit is contained in:
hamed
2026-07-10 11:42:26 +03:30
parent 778876b1f7
commit 9a3e84cc85
+25 -14
View File
@@ -22,11 +22,6 @@ export default function Altcha({ onVerified }) {
// null=در حال بررسی، true/false=فعال/غیرفعال بودن کپچا در سرور // null=در حال بررسی، true/false=فعال/غیرفعال بودن کپچا در سرور
const [enabled, setEnabled] = useState(null); const [enabled, setEnabled] = useState(null);
// ثبت custom element فقط در مرورگر (وابسته به customElements/DOM).
useEffect(() => {
import("altcha");
}, []);
useEffect(() => { useEffect(() => {
let alive = true; let alive = true;
fetch(`${API}/api/v1/altcha/config`) fetch(`${API}/api/v1/altcha/config`)
@@ -44,27 +39,43 @@ export default function Altcha({ onVerified }) {
}; };
}, [onVerified]); }, [onVerified]);
// ثبت custom element + ست‌کردن config به‌صورت attribute واقعی. در React 18
// پراپ‌های JSX روی custom element ممکن است به‌جای attribute به‌شکل property ست
// شوند و widget آن‌ها را نخواند (strings/theme اعمال نمی‌شد)؛ با setAttribute
// مطمئن می‌شویم درست خوانده می‌شوند. auto را آخر ست می‌کنیم تا بعد از config حل شود.
useEffect(() => { useEffect(() => {
const el = ref.current; if (enabled !== true) return;
if (!el) return;
const onStateChange = (e) => { const onStateChange = (e) => {
if (e.detail?.state === "verified" && e.detail.payload) { if (e.detail?.state === "verified" && e.detail.payload) {
onVerified(e.detail.payload); onVerified(e.detail.payload);
} }
}; };
el.addEventListener("statechange", onStateChange);
return () => el.removeEventListener("statechange", onStateChange); // attributeها را قبل از import (قبل از upgrade شدن element) ست می‌کنیم تا
}, [onVerified, enabled]); // widget از همان ابتدا با تم روشن و متن فارسی init شود.
const el = ref.current;
if (el) {
el.setAttribute("challengeurl", `${API}/api/v1/altcha/challenge`);
el.setAttribute("strings", FA_STRINGS);
el.setAttribute("theme", "light");
el.setAttribute("auto", "onload");
el.addEventListener("statechange", onStateChange);
}
import("altcha");
return () => {
el?.removeEventListener("statechange", onStateChange);
};
}, [enabled, onVerified]);
if (enabled !== true) return null; if (enabled !== true) return null;
return ( return (
<altcha-widget <altcha-widget
ref={ref} ref={ref}
challengeurl={`${API}/api/v1/altcha/challenge`} style={{ display: "block", marginTop: 16, marginBottom: 20 }}
auto="onload"
strings={FA_STRINGS}
style={{ display: "block", marginTop: 12 }}
/> />
); );
} }