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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.