Skip to content

Commit

Permalink
Prevent unnecessary rerenders for PlaidEmbeddedLink (#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
malthusplaid committed Jun 13, 2024
1 parent 0d81131 commit e025b96
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 4 deletions.
53 changes: 53 additions & 0 deletions src/PlaidEmbeddedLink.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';
import { render } from '@testing-library/react';
import { PlaidEmbeddedLink, PlaidLinkOptions } from './';

import useScript from 'react-script-hook';
jest.mock('react-script-hook');
const mockedUseScript = useScript as jest.Mock;

const ScriptLoadingState = {
LOADING: [true, null],
LOADED: [false, null],
ERROR: [false, 'SCRIPT_LOAD_ERROR'],
};

describe('PlaidEmbeddedLink', () => {
const config: PlaidLinkOptions = {
token: 'test-token',
onSuccess: jest.fn(),
onExit: jest.fn(),
onLoad: jest.fn(),
onEvent: jest.fn(),
};
const createEmbeddedSpy = jest.fn(() => ({
destroy: jest.fn(),
}));

beforeEach(() => {
mockedUseScript.mockImplementation(() => ScriptLoadingState.LOADED);
window.Plaid = {
createEmbedded: createEmbeddedSpy,
};
});

afterEach(() => {
jest.clearAllMocks();
});

it('should not rerender if config did not change', () => {
const styles = { height: '350px', width: '350px', backgroundColor: 'white' };
const { rerender } = render(<PlaidEmbeddedLink {...config} style={styles} />);
expect(createEmbeddedSpy).toHaveBeenCalledTimes(1);
rerender(<PlaidEmbeddedLink {...config} style={{...styles, backgroundColor: 'light-blue'}} />);
expect(createEmbeddedSpy).toHaveBeenCalledTimes(1);
});

it('should rerender if config did change', () => {
const { rerender } = render(<PlaidEmbeddedLink {...config} />);
expect(createEmbeddedSpy).toHaveBeenCalledTimes(1);
const newConfig = { ...config, token: 'new-test-token' };
rerender(<PlaidEmbeddedLink {...newConfig} />);
expect(createEmbeddedSpy).toHaveBeenCalledTimes(2);
});
});
30 changes: 27 additions & 3 deletions src/PlaidEmbeddedLink.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useMemo } from 'react';
import useScript from 'react-script-hook';

import { PLAID_LINK_STABLE_URL } from './constants';
import { PlaidEmbeddedLinkPropTypes } from './types';
import {
PlaidEmbeddedLinkPropTypes,
PlaidLinkOptionsWithLinkToken,
} from './types';

export const PlaidEmbeddedLink = (props: PlaidEmbeddedLinkPropTypes) => {
const { style, className, ...config } = props;
const {
style,
className,
onSuccess,
onExit,
onLoad,
onEvent,
token,
receivedRedirectUri,
} = props;

const config = useMemo<PlaidLinkOptionsWithLinkToken>(
() => ({
onSuccess,
onExit,
onLoad,
onEvent,
token,
receivedRedirectUri,
}),
[onSuccess, onExit, onLoad, onEvent, token, receivedRedirectUri]
);

// Asynchronously load the plaid/link/stable url into the DOM
const [loading, error] = useScript({
Expand Down
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ export type PlaidLinkPropTypes = PlaidLinkOptions & {
style?: React.CSSProperties;
};

export type PlaidEmbeddedLinkPropTypes = PlaidLinkOptions & {
export type PlaidEmbeddedLinkPropTypes = PlaidLinkOptionsWithLinkToken & {
className?: string;
style?: React.CSSProperties;
};
Expand Down

0 comments on commit e025b96

Please sign in to comment.