How to Implement Plaid Link with the Quiltt API
Once you have your App setup to run queries and mutations, you can use the Quiltt API to implement Plaid Link. This guide will give you a quick and easy way to integrate Plaid Link with the Quiltt API.
If you’re following the previous guide, we’ll be continuing where we left off with our project. Let’s start with installing the required dependencies for this step.
yarn add react-plaid-link
Next, we can create a new Plaid
folder in the src
directory.
We’ll create a LinkWidget.tsx
file within that new folder.
Then we can start with importing the required modules for this component
and build out its structure.
We’ll guide you through creating this component step-by-step so you can see how modular we can make this component.
There’s slightly more boilerplate than if you followed Plaid’s Guide, but at the end of this guide, we’ll be able to use this one component as a base for every possible Plaid integration.
AnchorBuilding the Link Component
AnchorStep 1: Import required packages
Add imports from react-plaid-link
and @apollo/client
right after react
and return an HTML button component.
import * as React from 'react'import { usePlaidLink } from 'react-plaid-link'import { gql, useMutation } from '@apollo/client'const PlaidConnectWidget = () => { return <button type="button">LinkWidget</button>}
AnchorStep 2: Destructure our props and assign them to the button
Besides className
and children
, the list of destructured props is the same as the list of inputs
that the connectorPlaidInitialize
mutation expects.
import * as React from 'react'import { usePlaidLink } from 'react-plaid-link'import { gql, useMutation } from '@apollo/client'
const PlaidConnectWidget = ({ className = '', children = 'Connect', products = undefined, androidPackageName = undefined, accountFilters = undefined, auth = undefined, clientMutationId = undefined, clientName = undefined, connectionId = undefined, countryCodes = undefined, euConfig = undefined, features = undefined, language = undefined, linkCustomizationName = undefined, update = undefined, onSuccess = undefined, onEvent = undefined, onExit = undefined, onLoad = undefined, ...otherProps}) => { return ( <button type="button" className={className} {...otherProps}> {children} </button> )}
AnchorStep 3: Add custom logic for the component
In this step, we will be adding the required states, callback functions, and mutations to our component.
Add these parts at the beginning of your component before the return statement.
First, start with initializing the state for linkToken
and connectorToken
. We will be using
these to track our tokens for Plaid Link and the Quiltt connector.
const [linkToken, setLinkToken] = React.useState(null)const [connectorToken, setConnectorToken] = React.useState('')
Next, we’ll add the connectorPlaidInitialize
and connectorPlaidClose
mutations for the connections.
See our docs for more information on these mutations.
const CONNECTOR_PLAID_CLOSE_MUTATION = gql` mutation ConnectorPlaidClose($input: ConnectorPlaidCloseInput) { connectorPlaidClose(input: $input) { errors { code message } success } } `
const CONNECTOR_PLAID_INITIALIZE_MUTATION = gql` mutation ConnectorPlaidInitialize($input: ConnectorPlaidInitializeInput) { connectorPlaidInitialize(input: $input) { record { connectorStatus connectorToken expiration linkToken requestId } errors { code type displayMessage message requestId } success } } `
Then, set an onCompleted
callback for the connectorPlaidInitialize
mutation. And initialize both mutations.
const handlePlaidTokenCreated = (data) => { if (data) { const { record } = data.connectorPlaidInitialize
if (record) { setLinkToken(record.linkToken) setConnectorToken(record.connectorToken) if (record.connectorStatus === 'CONTINUE') { // No action by user needed. Decide what to do next. } } }}
const [generateLinkToken] = useMutation(CONNECTOR_PLAID_INITIALIZE_MUTATION, { variables: { input: { products, androidPackageName, accountFilters, auth, clientMutationId, clientName, connectionId, countryCodes, euConfig, features, language, linkCustomizationName, update, }, }, fetchPolicy: 'no-cache', onCompleted: handlePlaidTokenCreated,})
const [saveConnection] = useMutation(CONNECTOR_PLAID_CLOSE_MUTATION, { fetchPolicy: 'no-cache',})
Finally, we can set up the Plaid Link config and add the click handler for our button.
const handleSuccess = (publicToken, metadata) => { if (publicToken && metadata) { saveConnection({ variables: { input: { connectorToken, publicToken, metadata } } }) if (onSuccess) { onSuccess(publicToken, metadata) } } else { // Handle Errors }}
const config = { token: linkToken, onSuccess: handleSuccess, onEvent, onExit, onLoad,}
const { open, ready } = usePlaidLink(config)
const handleClick = () => { if (ready && open) { open() }}
// If linkToken is not set, generate oneReact.useEffect(() => { if (!linkToken && generateLinkToken) { generateLinkToken() }}, [linkToken, generateLinkToken])
const disabled = !ready || !linkToken
And our button should now look like this
return ( <button type="button" className={className} disabled={disabled} onClick={handleClick} {...otherProps} > {children} </button> )
AnchorFinal Product
import * as React from 'react'import { usePlaidLink } from 'react-plaid-link'import { gql, useMutation } from '@apollo/client'
const PlaidConnectWidget = ({ className = '', children = 'Connect', products = undefined, androidPackageName = undefined, accountFilters = undefined, auth = undefined, clientMutationId = undefined, clientName = undefined, connectionId = undefined, countryCodes = undefined, euConfig = undefined, features = undefined, language = undefined, linkCustomizationName = undefined, update = undefined, onSuccess = undefined, onEvent = undefined, onExit = undefined, onLoad = undefined, ...otherProps}) => { const [linkToken, setLinkToken] = React.useState(null) const [connectorToken, setConnectorToken] = React.useState('')
const CONNECTOR_PLAID_CLOSE_MUTATION = gql` mutation ConnectorPlaidClose($input: ConnectorPlaidCloseInput) { connectorPlaidClose(input: $input) { errors { code message } success } } `
const CONNECTOR_PLAID_INITIALIZE_MUTATION = gql` mutation ConnectorPlaidInitialize($input: ConnectorPlaidInitializeInput) { connectorPlaidInitialize(input: $input) { record { connectorStatus connectorToken expiration linkToken requestId } errors { code type displayMessage message requestId } success } } `
const handlePlaidTokenCreated = (data) => { if (data) { const { record } = data.connectorPlaidInitialize
if (record) { setLinkToken(record.linkToken) setConnectorToken(record.connectorToken) if (record.connectorStatus === 'CONTINUE') { // No action by user needed. Decide what to do next. } } } }
const [generateLinkToken] = useMutation(CONNECTOR_PLAID_INITIALIZE_MUTATION, { variables: { input: { products, androidPackageName, accountFilters, auth, clientMutationId, clientName, connectionId, countryCodes, euConfig, features, language, linkCustomizationName, update, }, }, fetchPolicy: 'no-cache', onCompleted: handlePlaidTokenCreated, })
const [saveConnection] = useMutation(CONNECTOR_PLAID_CLOSE_MUTATION, { fetchPolicy: 'no-cache', })
const handleSuccess = (publicToken, metadata) => { if (publicToken && metadata) { saveConnection({ variables: { input: { connectorToken, publicToken, metadata } } }) if (onSuccess) { onSuccess(publicToken, metadata) } } else { // Handle Errors } }
const config = { token: linkToken, onSuccess: handleSuccess, onEvent, onExit, onLoad, }
const { open, ready } = usePlaidLink(config)
const handleClick = () => { if (ready && open) { open() } }
// If linkToken is not set, generate one React.useEffect(() => { if (!linkToken && generateLinkToken) { generateLinkToken() } }, [linkToken, generateLinkToken])
const disabled = !ready || !linkToken
return ( <button type="button" className={className} disabled={disabled} onClick={handleClick} {...otherProps} > {children} </button> )}
export default PlaidConnectWidget
AnchorUsage
Here’s an example of how to use the Plaid Link component.
import * as React from 'react'import PlaidConnectWidget from './PlaidConnectWidget'const Component = () => { const plaidLinkOptions = { /* Add options to customize Plaid Link here */ products: ['transactions', 'liabilities'], } const handleExit = (error, metadata) => { console.log(error) } const handleLoad = () => { console.log('Loaded') } const handleEvent = (eventName, metadata) => { console.log(eventName) } return ( <PlaidConnectWidget onExit={handleExit} onLoad={onLoad} onEvent={onEvent} {...plaidLinkOptions}> Button Text </PlaidConnectWidget> )}export default Component