Ok, I've officially spent hours trying to figure this out and yet I'm sure its a simple fix. I'm brand new to React and trying to create a custom component for Plotly Dash.
Problem
I am trying to update the token property of the LoginForm
component which makes use of the Plaid link for anyone that is familiar. You will notice in the handleOnSuccess
function in LoginForm.react.js
I am able to retrieve the token and display it in the console. All I want to do is update the token
property of the LoginForm
with that value displayed in the console.
Below is the entire LoginForm.react.js
:
import React, { Component } from 'react';
import Script from 'react-load-script';
import PropTypes from 'prop-types';
class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {
linkLoaded: false,
initializeURL: 'https://cdn.plaid.com/link/v2/stable/link-initialize.js',
};
this.onScriptError = this.onScriptError.bind(this);
this.onScriptLoaded = this.onScriptLoaded.bind(this);
this.handleLinkOnLoad = this.handleLinkOnLoad.bind(this);
this.handleOnExit = this.handleOnExit.bind(this);
this.handleOnEvent = this.handleOnEvent.bind(this);
this.handleOnSuccess = this.handleOnSuccess.bind(this);
this.renderWindow = this.renderWindow.bind(this);
}
onScriptError() {
console.error('There was an issue loading the link-initialize.js script');
}
onScriptLoaded() {
window.linkHandler = window.Plaid.create({
apiVersion: this.props.apiVersion,
clientName: this.props.clientName,
env: this.props.env,
key: this.props.publicKey,
onExit: this.handleOnExit,
onLoad: this.handleLinkOnLoad,
onEvent: this.handleOnEvent,
onSuccess: this.handleOnSuccess,
product: this.props.product,
selectAccount: this.props.selectAccount,
token: this.props.token,
webhook: this.props.webhook,
});
console.log("Script loaded");
}
handleLinkOnLoad() {
console.log("loaded");
this.setState({ linkLoaded: true });
}
handleOnSuccess(token, metadata) {
console.log(token);
console.log(metadata);
}
handleOnExit(error, metadata) {
console.log('link: user exited');
console.log(error, metadata);
}
handleOnLoad() {
console.log('link: loaded');
}
handleOnEvent(eventname, metadata) {
console.log('link: user event', eventname, metadata);
}
renderWindow() {
const institution = this.props.institution || null;
if (window.linkHandler) {
window.linkHandler.open(institution);
}
}
static exit(configurationObject) {
if (window.linkHandler) {
window.linkHandler.exit(configurationObject);
}
}
render() {
return (
<div id={this.props.id}>
{this.renderWindow()}
<Script
url={this.state.initializeURL}
onError={this.onScriptError}
onLoad={this.onScriptLoaded}
/>
</div>
);
}
}
LoginForm.defaultProps = {
apiVersion: 'v2',
env: 'sandbox',
institution: null,
selectAccount: false,
style: {
padding: '6px 4px',
outline: 'none',
background: '#FFFFFF',
border: '2px solid #F1F1F1',
borderRadius: '4px',
},
};
LoginForm.propTypes = {
// id
id: PropTypes.string,
// ApiVersion flag to use new version of Plaid API
apiVersion: PropTypes.string,
// Displayed once a user has successfully linked their account
clientName: PropTypes.string.isRequired,
// The Plaid API environment on which to create user accounts.
// For development and testing, use tartan. For production, use production
env: PropTypes.oneOf(['tartan', 'sandbox', 'development', 'production']).isRequired,
// Open link to a specific institution, for a more custom solution
institution: PropTypes.string,
// The public_key associated with your account; available from
// the Plaid dashboard (https://dashboard.plaid.com)
publicKey: PropTypes.string.isRequired,
// The Plaid products you wish to use, an array containing some of connect,
// auth, identity, income, transactions, assets
product: PropTypes.arrayOf(
PropTypes.oneOf([
// legacy product names
'connect',
'info',
// normal product names
'auth',
'identity',
'income',
'transactions',
'assets',
])
).isRequired,
// Specify an existing user's public token to launch Link in update mode.
// This will cause Link to open directly to the authentication step for
// that user's institution.
token: PropTypes.string,
// Set to true to launch Link with the 'Select Account' pane enabled.
// Allows users to select an individual account once they've authenticated
selectAccount: PropTypes.bool,
// Specify a webhook to associate with a user.
webhook: PropTypes.string,
// A function that is called when a user has successfully onboarded their
// account. The function should expect two arguments, the public_key and a
// metadata object
onSuccess: PropTypes.func,
// A function that is called when a user has specifically exited Link flow
onExit: PropTypes.func,
// A function that is called when the Link module has finished loading.
// Calls to plaidLinkHandler.open() prior to the onLoad callback will be
// delayed until the module is fully loaded.
onLoad: PropTypes.func,
// A function that is called during a user's flow in Link.
// See
onEvent: PropTypes.func,
// Button Styles as an Object
style: PropTypes.object,
// Button Class names as a String
className: PropTypes.string,
};
export default LoginForm;
And here is App.js
:
// /* eslint no-magic-numbers: 0 */
import React, { Component } from 'react';
import { LoginForm } from '../lib';
class App extends Component {
constructor(props) {
super(props);
this.state = {
token: null
}
}
render() {
return (
<LoginForm
id="Test"
clientName="Plaid Client"
env="sandbox"
product={['auth', 'transactions']}
publicKey="7a3daf1db208b7d1fe65850572eeb1"
className="some-class-name"
apiVersion="v2"
token={this.state.token}
>
</LoginForm>
);
}
}
export default App;
I believe that it is essential to prevent the assignment of any function to a property of LoginForm
i.e. token={this.someFunction}
is not acceptable
I also know that it's not preferable (if it's even possible) to directly change the value of a property i.e. logically the insertion of this.props.token=token
into the handleOnSuccess
function might work (LOGICALLY - I know it doesn't) but that still doesn't really provide a sound flow of updating components between the parent and child processes.
I appreciate any and all help as this is literally the LAST step in this little project and I really cant figure it out. Thanks in advance!
If it makes it easier - you can clone the repo here: https://github.com/SterlingButters/plaidash