Search code examples
javascriptreactjsreact-reduxplaid

react-redux action creator not available on props


I am trying to use react-plaid-link to integrate plaid in to my app. Everything works fine until I execute the handleOnSuccess callback. I get the following error message:

Uncaught TypeError: Cannot read property 'createTransferSource' of undefined

For some reason my action creators, exported out of '../../actions' aren't available when I call handleOnSuccess

This is my component

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import PlaidLink from 'react-plaid-link';
import * as actions from '../../actions';

const plaidPublicKey = process.env.REACT_APP_PLAID_PUBLIC_KEY;

class PlaidAuthComponent extends Component {

  handleOnSuccess(token, metadata) {
    // send token to client server
    this.props.createTransferSource(metadata);  
  }

  render() {
    return (
      <div>
        <PlaidLink
          publicKey={`${plaidPublicKey}`}
          product="auth"
          env="sandbox"
          clientName="plaidname"
          onSuccess={this.handleOnSuccess}
          />
      </div>
    );
  }
}

export default connect(null, actions )(PlaidAuthComponent);

from my index.js file in my actions folder

export * from './transfer_actions';

my transfer_actions.js file

export const createTransferSource = (values, callback) => {
  return function (dispatch){

  axios({
    method : 'POST',
    url: `xxx/transfer_source.json`, 
    data: { values } 
  })
    .then(response => {
      dispatch({ 
        type: CREATE_TRANSFER_SOURCE,
        payload: response
      });
    })
    .then(() => callback())
    .catch( error => {
    dispatch({
      type: CREATE_TRANSFER_SOURCE_ERROR,
      payload: error.response
    });
    });
  };
};

Solution

  • You need to bind this otherwise you would lose it in your component.

    You could do this in several ways:

    Method One:
    Using arrow function

    handleOnSuccess = (token, metadata) => {
      this.props.createTransferSource(metadata);
    }
    

    Method Two:
    Binding in the constructor.

    constructor(props) {
       super(props);
    
       this.handleOnSuccess = this.handleOnSuccess.bind(this); 
    }
    

    Method Three:
    Binding directly where handleOnSuccess was referenced.

    render() {
        return (
          <div>
            <PlaidLink
              publicKey={`${plaidPublicKey}`}
              product="auth"
              env="sandbox"
              clientName="plaidname"
              onSuccess={this.handleOnSuccess.bind(this)}
              />
          </div>
       );
    }
    

    Method Four:
    Invoking handleOnSuccess reference with an arrow function

    render() {
        return (
          <div>
            <PlaidLink
              publicKey={`${plaidPublicKey}`}
              product="auth"
              env="sandbox"
              clientName="plaidname"
              onSuccess={() => this.handleOnSuccess}
              />
          </div>
       );
    }