簡體   English   中英

React:更新組件屬性

[英]React: Updating Component Property

好的,我已經正式花了幾個小時試圖解決這個問題,但我確定這是一個簡單的解決方法。 我是 React 的新手,正在嘗試為 Plotly Dash 創建自定義組件。

問題

我正在嘗試更新LoginForm組件的令牌屬性,該組件為熟悉的任何人使用 Plaid 鏈接。 您會注意到在LoginForm.react.jshandleOnSuccess函數中,我能夠檢索令牌並將其顯示在控制台中。 我想要做的就是使用控制台中顯示的值更新LoginFormtoken屬性。

下面是整個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;

這是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;

我認為必須防止將任何函數分配給LoginForm的屬性,即token={this.someFunction}是不可接受的

我也知道直接更改屬性的值是不可取的(如果可能的話),即邏輯上將this.props.token=token插入到handleOnSuccess函數中可能會起作用(邏輯上 - 我知道它沒有)但是這仍然沒有真正提供在父進程和子進程之間更新組件的健全流程。

我感謝任何和所有幫助,因為這實際上是這個小項目的最后一步,我真的無法弄清楚。 提前致謝!

如果它更容易 - 您可以在此處克隆存儲庫: https : //github.com/SterlingButters/plaidash

您可以在 App 中使用handleUpdateToken方法,將其作為道具傳遞給 LoginForm:

class App extends Component {
  ...
  handleUpdateToken(token) {
    this.setState({ token });
  }

  ...
  render() {
    return (
      <LoginForm
        onUpdateToken={this.handleUpdateToken}
        ...other LoginForm props
      />
  }
}

在登錄表單中:

handleOnSuccess(token, metadata) {
  console.log(token);
  console.log(metadata);
  this.props.onUpdateToken(token);
}

是的,您已經接近了 - 您需要在App組件中定義一個updateToken函數,該函數使用this.setState

updateToken函數作為道具傳遞給LoginForm LoginForm組件應該在handleOnSuccess調用這個函數。

App.react.js

// pass this function as prop to LoginForm.
// don't forget to bind to 'this'.
updateToken(token, metadata) {
    ...
    this.setState({ token })
}

...

// in render function
<LoginForm updateToken={updateToken} ... />

LoginForm.react.js

handleOnSuccess(token, metadata) {
    this.props.updateToken(token, metadata)
}

您避免分配給props是完全正確的。 使用此方法,您將更新 props 的責任委托給父級,並確保狀態和更新函數位於同一組件中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM