0

I have an application using the teller.io API. I have to import a script from them to initiate authentication within my react app, as they have no react library.

After adding the script to the DOM, I have to use a function from it. However, React won't recognize the function as it's only defined at runtime when the script is added.

The following is my solution, and it works, but I know this cannot be a good way to accomplish this so if anyone can recommend a proper solution that'd be amazing.

useEffect(() => { const script = document.createElement("script"); script.src = "https://cdn.teller.io/connect/connect.js"; script.async = true; document.head.appendChild(script); var tellerConnect = window.TellerConnect.setup({ applicationId: "Your application ID e.g app_xxxxxx", onInit: function() { console.log("Teller Connect has initialized"); }, // Part 3. Handle a successful enrollment's accessToken onSuccess: function(enrollment) { console.log("User enrolled successfully", enrollment.accessToken); }, onExit: function() { console.log("User closed Teller Connect"); } }); var el = document.getElementById("myButton"); el.addEventListener("click", function() { // tellerConnect.open(); }); }, []); 

Line 6, with the "window.TellerConnect.setup is what I'd like to fix/replace with a more proper solution.

Teller.io docs for this script/setup can be found at: Teller Connect

Thanks in advance!

1
  • "React won't recognize" is not the problem – React doesn't care. The problem is you're not waiting for the script to load before calling setup... Commented Nov 4, 2021 at 6:34

1 Answer 1

2

A pattern (a hook and a pure-JS loader) like this might work for you.

This doesn't take into account multiple components attempting to use the API with e.g. different application IDs.

function loadScript(elementId, src) { if (!document.getElementById(elementId)) { const script = document.createElement('script'); script.src = src; script.id = elementId; document.head.appendChild(script); } } /** * Ensure the Teller Connect script is loaded. * * Returns the `window.TellerConnect` object once it exists. */ function loadTellerConnect() { return new Promise((resolve) => { function check() { if (window.TellerConnect) { return resolve(window.TellerConnect); } loadScript('teller-script', 'https://cdn.teller.io/connect/connect.js'); setTimeout(check, 100); } check(); }); } /** * Load and configure Teller Connect. * @returns The Teller API (or null if it hasn't yet loaded). */ function useTellerAPI(setupArgs) { const [tellerApi, setTellerApi] = React.useState(null); React.useEffect(() => { loadTellerConnect().then((tellerApi) => { tellerApi.setup(setupArgs); setTellerApi(tellerApi); }); }, [setupArgs]); return tellerApi; } function MyComponent() { const tellerConnect = useTellerAPI({ applicationId: 'Your application ID e.g app_xxxxxx', }); return ( <button onClick={() => tellerConnect?.open()} disabled={!tellerConnect}> Open Teller </button> ); } 
Sign up to request clarification or add additional context in comments.

3 Comments

This is much cleaner, thanks!
Only issue I ran into with this solution, was I had to modify the "useTellerApi" function a bit. I had to change "tellerApi.setup(setupArgs);" and "setTellerApi(tellerApi);" to just "setTellerApi(tellerApi.setup(setupArgs));". Reason being, the TellerConnect object does not have an "open()" function, but the object returned by "TellerConnect.setup()" does
Ah, sure. I didn't read the docs that thoroughly. Glad I could help anyway!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.