Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
16
rated 0 times [  19] [ 3]  / answers: 1 / hits: 5412  / 5 Years ago, sat, february 9, 2019, 12:00:00

Problem:



Currently, I have a LoginForm component that has an on-success handler function handleOnSuccess. This the then linked to the parent component with an onTokenUpdate property defined by a token-update handler function handleUpdateToken. The problem is that the setState in the handleUpdateToken function is forcing an undesired rerender.



Desired Outcome:



What I ultimately need is to update the LoginForm component property token with the value obtained on success WITHOUT performing a rerender. Is this even possible? According to React: Update Child Component Without Rerendering Parent it would seem it is not, however, no feasible alternative for my case was suggested. Im wondering if anyone had any suggested alternatives if this is not possible.



Code



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);
this.props.onTokenUpdate(token);
}
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,
access_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,


onTokenUpdate: PropTypes.func,

// Button Styles as an Object
style: PropTypes.object,

// Button Class names as a String
className: PropTypes.string,
};

export default LoginForm;


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 = {
access_token: null
};
this.handleUpdateToken = this.handleUpdateToken.bind(this)
}

handleUpdateToken(access_token) {
this.setState({ access_token: access_token });
}

render() {
return (
<LoginForm
id=Test
clientName=Plaid Client
env=sandbox
product={['auth', 'transactions']}
publicKey=7a3daf1db208b7d1fe65850572eeb1
className=some-class-name
apiVersion=v2
onTokenUpdate={this.handleUpdateToken}
token={this.state.access_token}
>
</LoginForm>
);
}
}

export default App;


Thanks in advance for any/all help!


More From » reactjs

 Answers
2

You cannot prevent rendering of parent if you want to update the props of child. But there is a way to achieve it.




  1. You need to store the token in side your LoginForm state.

  2. You need to change change the state of the LoginForm in componentWillReceiveProps

  3. You need to pass a token and function in this.props.onTokenUpdate(token,function);.This function will have an argument which is token from parent. And inside function you will change the state.(This is needed if you want to alter the token in parent component and send updated one).

  4. The token in parent shouldn't be in the state if you want to prevent render(). It should be compoent property

  5. Use this.state.tokenInstead of this.props.token



Below is a general example.
Codepen


[#9006] Friday, February 8, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
grayson

Total Points: 36
Total Questions: 113
Total Answers: 95

Location: Tonga
Member since Fri, Aug 21, 2020
4 Years ago
;