Skip to main content

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.

Skip to the end to see the finished 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 one
React.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