reactjsreact-nativeplaid

Plaid api react native won't start the the auth flow


I am using plaid in my react native app and trying to follow the Quickstart project as a reference. I am successfully able to generate the link token in sandbox env. But when I tap on the PlaidLink component in the react native app, it doesn't do anything and it gives me some error which I am attaching below.

Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'create' of null
TypeError: Cannot read property 'create' of null
    at ?anon_0_ (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:130387:52)
    at next (native)
    at anonymous (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:130348:73)
    at tryCallTwo (/private/var/folders/yw/6bx918xn4671rggfcdxz7fph0000gn/T/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:61:9)
    at doResolve (/private/var/folders/yw/6bx918xn4671rggfcdxz7fph0000gn/T/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:216:25)
    at Promise (/private/var/folders/yw/6bx918xn4671rggfcdxz7fph0000gn/T/hermes/build_iphonesimulator/lib/InternalBytecode/InternalBytecode.js:82:14)
    at anonymous (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:130330:36)
    at openLink (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:130369:21)
    at onPress (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:130416:15)
    at _performTransitionSideEffects (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:81778:22)
    at _receiveSignal (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:81728:45)
    at onResponderRelease (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:81584:34)
    at apply (native)
    at invokeGuardedCallbackProd (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:82294:21)
    at apply (native)
    at invokeGuardedCallback (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:82470:42)
    at apply (native)
    at invokeGuardedCallbackAndCatchFirstError (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:82484:36)
    at executeDispatch (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:82561:48)
    at executeDispatchesInOrder (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:82583:26)
    at executeDispatchesAndRelease (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84354:35)
    at executeDispatchesAndReleaseTopLevel (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84361:43)
    at forEach (native)
    at forEachAccumulated (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:83175:22)
    at runEventsInBatch (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84374:27)
    at runExtractedPluginEventsInBatch (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84484:25)
    at anonymous (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84455:42)
    at batchedUpdates$1 (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:97896:20)
    at batchedUpdates (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84330:36)
    at _receiveRootNodeIDEvent (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84454:23)
    at receiveTouches (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:84543:34)
    at apply (native)
    at __callFunction (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:3679:36)
    at anonymous (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:3399:31)
    at __guard (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:3616:15)
    at callFunctionReturnFlushedQueue (http://192.168.100.11:8081/node_modules/expo/AppEntry.bundle//&platform=ios&dev=true&hot=false&lazy=true:3398:21)
 LOG  Link token is  link-sandbox-c29d2a47-2da9-4a7b-a56d-9d02edc46c2d

This is my screen which has just a button that says add bank and clicking on that will start the whole procedure.

import { StatusBar } from 'expo-status-bar';
import { useState, useCallback, useEffect } from 'react';

import { StyleSheet, Text, View, Dimensions } from 'react-native';
import PlaidLink, { LinkSuccess, LinkExit, usePlaidEmitter } from 'react-native-plaid-link-sdk';


let height = Dimensions.get('window').height;
let width = Dimensions.get('window').width;

export default function App() {

  const [linkToken, setLinkToken] = useState(null);
  const address = '7019-116-90-112-9.ngrok-free.app'//Platform.OS === 'ios' ? 'localhost' : '10.0.2.2';



  const createLinkToken = useCallback(async () => {
    await fetch(`https://${address}/api/plaid/create_link_token`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      // "Authorization": "Bearer " + u.token,
    },
    body: JSON.stringify({ address: address })
    })
    .then((response) => response.json())
    .then((data) => {
      console.log(data.data.link_token)
      setLinkToken(data.data.link_token);
    })
    .catch((err) => {
      console.log(err);
    });
  }, [setLinkToken])

  useEffect(() => {
    if (linkToken == null) {
      createLinkToken();
    }
    console.log("Link token is ", linkToken)
  }, [linkToken]);

  
  return (
    <View style={{flex: 1, height: height, width: width, justifyContent: 'center', alignItems: 'center'}}>
      
      <View style={styles.bottom}>
        <PlaidLink
          tokenConfig={{
            token: linkToken,
            logLevel: 'DEBUG'
          }}
          onSuccess={(success) => {
            console.log(success);
          }}
          onExit={(exit) => {
            // console.log(exit);
          }}
        >
          <Text>Add Account</Text>
        </PlaidLink>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'red',
    alignItems: 'center',
    justifyContent: 'center',
    height: height,
    width: width
  },
});

What could be the possible issue? I am not able to figure this out.


Solution

  • Asked and answered on Plaid's GitHub, posting new answer here for visibility. Deleted my old answer as it was not correct.

    The error Argument 1 (BOOL) of RNLinksdk.create must not be null is the result of the call to export const PlaidLink = (props: PlaidLinkComponentProps) which calls NativeModules.RNLinksdk.create(config.token, config.noLoadingState) which calls the native code RCT_EXPORT_METHOD(create:(NSString*)token :(BOOL)noLoadingState) which requires a variable called noLoadingState. Since you're not passing this bool you get this error.

    This variable should be optional, but it's not.

    You can resolve the issue by using the code in the README of the repo.