fix: mount mollie components after DOM ready via useEffect

This commit is contained in:
Usman Baig
2026-03-26 22:03:23 +01:00
parent 512368d79e
commit 22dddc6b6f

View File

@@ -38,40 +38,56 @@ export default function PaymentForm({ plan, interval, limit }: PaymentFormProps)
cardCvc: null, cardCvc: null,
}) })
const mountMollieComponents = () => { const [scriptLoaded, setScriptLoaded] = useState(false)
const mollie = initMollie()
if (!mollie) {
setMollieError(true)
return
}
try { // Mount Mollie components AFTER both script loaded AND DOM elements exist
const fields: Array<{ type: string; selector: string }> = [ useEffect(() => {
{ type: 'cardNumber', selector: '#mollie-card-number' }, if (!scriptLoaded) return
{ type: 'cardExpiry', selector: '#mollie-card-expiry' },
{ type: 'cardCvc', selector: '#mollie-card-cvc' },
]
for (const { type, selector } of fields) { // Small delay to ensure DOM elements are painted
const component = mollie.createComponent(type, { styles: MOLLIE_FIELD_STYLES }) const timer = setTimeout(() => {
component.mount(selector) const mollie = initMollie()
component.addEventListener('change', (event: unknown) => { if (!mollie) {
const e = event as { error?: string; touched?: boolean } setMollieError(true)
setCardErrors((prev) => { return
const next = { ...prev }
if (e.error) next[type] = e.error
else delete next[type]
return next
})
})
componentsRef.current[type] = component
} }
setMollieReady(true) try {
} catch { const fields: Array<{ type: string; selector: string }> = [
setMollieError(true) { type: 'cardNumber', selector: '#mollie-card-number' },
} { type: 'cardExpiry', selector: '#mollie-card-expiry' },
} { type: 'cardCvc', selector: '#mollie-card-cvc' },
]
for (const { type, selector } of fields) {
const el = document.querySelector(selector)
if (!el) {
setMollieError(true)
return
}
const component = mollie.createComponent(type, { styles: MOLLIE_FIELD_STYLES })
component.mount(el)
component.addEventListener('change', (event: unknown) => {
const e = event as { error?: string; touched?: boolean }
setCardErrors((prev) => {
const next = { ...prev }
if (e.error) next[type] = e.error
else delete next[type]
return next
})
})
componentsRef.current[type] = component
}
setMollieReady(true)
} catch (err) {
console.error('Mollie mount error:', err)
setMollieError(true)
}
}, 100)
return () => clearTimeout(timer)
}, [scriptLoaded])
// Cleanup Mollie components on unmount // Cleanup Mollie components on unmount
useEffect(() => { useEffect(() => {
@@ -126,7 +142,7 @@ export default function PaymentForm({ plan, interval, limit }: PaymentFormProps)
<> <>
<Script <Script
src="https://js.mollie.com/v1/mollie.js" src="https://js.mollie.com/v1/mollie.js"
onLoad={mountMollieComponents} onLoad={() => setScriptLoaded(true)}
onError={() => setMollieError(true)} onError={() => setMollieError(true)}
/> />