I'm trying to import a script called Mollie (used for payments), but I'm not sure how to do it in React. Normally in Javascript you would do something like this:
<html>
<head>
<title>My Checkout</title>
</head>
<body>
<script src="https://js.mollie.com/v1/mollie.js"></script>
</body>
</html>
I've tried this (according to other Stackoverflow posts)
useEffect(() => {
const script = document.createElement("script");
script.src = "https://js.mollie.com/v1/mollie.js";
script.addEventListener("load", () => setScriptLoaded(true));
document.body.appendChild(script);
}, []);
const mollie = Mollie(); // Mollie is not defined
But then Mollie is undefined. Can anyone point in the right direction on how to import Mollie in React?
I'm following this guide (but it's for standard Javascript)
the point here is that the effect is being invoked after the react component mounted and rendered to the user. The next line where you are trying to call Mollie in fact running earlier when component is being constructed but not rendered yet.
There are multiple options what you can do about it:
// MollieExample.jsx
const MollieExample = () => {
const [mollie, setMollie] = useState();
useEffect(() => {
const script = document.createElement('script');
script.src = 'https://js.mollie.com/v1/mollie.js';
script.addEventListener("load", () => {
setMollie(window.Mollie(/* Mollie arguments */);
});
document.body.appendChild(script);
}, []);
useEffect(() => {
if (mollie) {
console.log('Mollie exists here');
console.log(typeof mollie);
}
} , [mollie]);
return <p>typeof mollie: {typeof mollie}</p>;
};
// useMollie.js
let molliePromise;
const useMollie = (effect, deps) => {
const [mollie, setMollie] = useState();
const mollieCb = useCallback((mollie) => effect(mollie), deps);
useEffect(() => {
if (!molliePromise) {
molliePromise = new Promise((resolve) => {
const script = document.createElement("script");
script.src = "https://js.mollie.com/v1/mollie.js";
script.addEventListener("load", () => {
resolve(window.Mollie(/* Mollie arguments */);
});
document.body.appendChild(script);
});
}
molliePromise.then((mollie) => setMollie(mollie));
}, []);
useEffect(() => {
if (mollie) {
mollieCb(mollie);
}
}, [mollie, mollieCb]);
};
// MollieConsumer.jsx
const MollieConsumer = () => {
useMollie((mollie) => {
console.log('Mollie exists here');
console.log(typeof mollie);
}, [/* useMollie effect callback dependencies array */]);
return (
<p>Mollie consumer</p>
);
};
// App.jsx
function App() {
/* Both consumers use the same instance of Mollie */
return (
<div>
<MollieConsumer/>
<MollieConsumer/>
</div>
);
}
I assume you will end up with using some middle option. For instance, with importing script in the index.html (or any other sort of the HTML page you have containing the React application host element) and global hook.