Search code examples
javascriptreact-hooksdrizzle

error during drizzle useCacheCall(): TypeError: Cannot read property 'methods' of undefined


I'm trying to invoke the drizzle useCacheCall() hook of a React Component from two different places. This is the invoked React component

const FamilyContainer = ({ member }) => {
  console.log("inside family container, member: ", member);
  const { useCacheCall } = drizzleReactHooks.useDrizzle();
  const organization = useCacheCall("MyContract", "getOrganization", member);
  console.log("organization: ", organization && organization);

  const maxLevel = useCacheCall("MyContract", "levels");
  console.log("maxLevel: ", maxLevel && typeof maxLevel);

  if (!isLoaded(organization) || !isLoaded(maxLevel)) {
    return "loading...";
  }
  if (isEmpty(organization) || isEmpty(maxLevel)) return <PageNotFound />;

  return (
    <FamilySection
      organization={organization}
      maxLevel={parseInt(maxLevel, 10)}
    />
  );
};

export default FamilyContainer;

I'm invoking the above mentioned React Component from the first location by copy pasting the url to the browser address bar: http://localhost:3000/#/invited/7434DC1BF0, which is successfully executing. this is the invocation code:

const InviteReceived = ({ playerAccount, inviterData }) => {
  const useStyles = makeStyles((theme) => ({
    root: {
      flexGrow: 1,
    },
  }));
  const classes = useStyles();
  const history = useHistory();

  return (
    <Grid container spacing={0}>
      <Grid item xs={12} sm={12} md={12} lg={5}>
        <Box
          display="flex"
          flexDirection="column"
          justifyContent="center"
          p={1}
          m={0}
          bgcolor="black"
        >
          <InviteReceivedSection
            playerAccount={playerAccount}
            inviterAccount={inviterData.ID}
          />
          <PayTributeSection playerAccount={playerAccount} />
        </Box>
      </Grid>
      <Grid item xs={12} sm={12} md={12} lg={7}>
        <FamilyContainer member={inviterData.ID} />
      </Grid>
    </Grid>
  );
};

export default InviteReceived;

The invocation from second location of the exact same React Component, by copy pasting the url to the browser address bar: http://localhost:3000/#/member/0x16Aa59291f0C27586B87CDcF48630cB721Dcd0cC , keeps repeatedly failing with the error message: TypeError: Cannot read property 'methods' of undefined. But if I run the first invocation first and then invoke the second component (using URLs), then error doesnt happen (weird).

const MemberComponent = ({ playerAccount }) => {
  console.log("Inside member component, playeraccount ", playerAccount);

  const useStyles = makeStyles((theme) => ({
    root: {
      flexGrow: 1,
    },
  }));
  const classes = useStyles();
  const history = useHistory();

  return (
    <Grid container spacing={0}>
      <Grid item xs={12} sm={12} md={12} lg={5}>
        <Box
          display="flex"
          flexDirection="column"
          justifyContent="center"
          p={1}
          m={0}
          bgcolor="black"
        >
          <ProfileDetailsSection playerAccount={playerAccount} />
          <RecruitSection playerAccount={playerAccount} />
        </Box>
      </Grid>
      <Grid item xs={12} sm={12} md={12} lg={7}>
        <FamilyContainer member={playerAccount} />
      </Grid>
    </Grid>
  );
};

export default MemberComponent;

This is the Error Trace:

 TypeError: Cannot read property 'methods' of undefined
    current
    C:/src/hooks/create-use-cache-call.js:19
      16 |     {}
      17 |   )
      18 | } else {
    > 19 |   const instance = drizzle.contracts[contractNameOrNames]
         | ^  20 |   const cacheKey = instance.methods[methodNameOrFunction].cacheCall(...args)
      21 |   const cache =
      22 |     drizzleState.contracts[contractNameOrNames][methodNameOrFunction][
    View compiled
    e.useDrizzleState
    C:/src/hooks/index.js:36
      33 | 
      34 | // This is the escape hatch mentioned above. We keep a ref to `args` and whenever they change, we immediately update the state just like in the subscription.
      35 | // This won't have any effect if `args` is undefined.
    > 36 | const argsRef = useRef(args)
         | ^  37 | const [state, setState] = useState(
      38 |   mapStateRef.current(drizzle.store.getState())
      39 | )
    View compiled
    (anonymous function)
    C:/src/hooks/create-use-cache-call.js:8
       5 |   methodNameOrFunction,
       6 |   ...args
       7 | ) => {
    >  8 |   const isFunction = typeof methodNameOrFunction === 'function'
       9 |   const drizzleState = useDrizzleState(drizzleState => {
      10 |     if (isFunction) {
      11 |       return contractNameOrNames.reduce(
    View compiled
    FamilyContainer
    C:/code/MyContract/codebase/client/src/containers/FamilyContainer.js:10
       7 | const FamilyContainer = ({ member }) => {
       8 |   console.log("inside family container, member: ", member);
       9 |   const { useCacheCall } = drizzleReactHooks.useDrizzle();
    > 10 |   const organization = useCacheCall("MyContract", "getOrganization", member);
      11 |   console.log("organization: ", organization && organization);
      12 | 
      13 |   const maxLevel = useCacheCall("MyContract", "levels");
    View compiled
    ▶ 16 stack frames were collapsed.
    Module../src/index.js
    C:/code/MyContract/codebase/client/src/index.js:100
       97 | const drizzle = new Drizzle(drizzleOptions, reduxStore);
       98 | console.log("Drizzle: ", drizzle, " reduxStore: ", reduxStore);
       99 | 
    > 100 | ReactDOM.render(
      101 |   <React.StrictMode>
      102 |     <ThemeProvider theme={theme}>
      103 |       <drizzleReactHooks.DrizzleProvider drizzle={drizzle}>
    View compiled
    __webpack_require__
    C:/code/MyContract/codebase/client/webpack/bootstrap:784
      781 | };
      782 | 
      783 | // Execute the module function
    > 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
          | ^  785 | 
      786 | // Flag the module as loaded
      787 | module.l = true;
    View compiled
    fn
    C:/code/MyContract/codebase/client/webpack/bootstrap:150
      147 |     );
      148 |     hotCurrentParents = [];
      149 |   }
    > 150 |   return __webpack_require__(request);
          | ^  151 | };
      152 | var ObjectFactory = function ObjectFactory(name) {
      153 |   return {
    View compiled
    1
    http://localhost:3000/static/js/main.chunk.js:7398:18
    __webpack_require__
    C:/code/MyContract/codebase/client/webpack/bootstrap:784
      781 | };
      782 | 
      783 | // Execute the module function
    > 784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
          | ^  785 | 
      786 | // Flag the module as loaded
      787 | module.l = true;
    View compiled
    checkDeferredModules
    C:/code/MyContract/codebase/client/webpack/bootstrap:45
      42 |  }
      43 |  if(fulfilled) {
      44 |    deferredModules.splice(i--, 1);
    > 45 |    result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
         | ^  46 |  }
      47 | }
      48 | 
    View compiled
    Array.webpackJsonpCallback [as push]
    http://localhost:3000/static/js/bundle.js:33:19
      30 | /******/     deferredModules.push.apply(deferredModules, executeModules || []);
      31 | /******/
      32 | /******/     // run deferred modules when all chunks ready
    > 33 | /******/     return checkDeferredModules();
         |                   ^  34 | /******/   };
      35 | /******/   function checkDeferredModules() {
      36 | /******/     var result;
    View source

UPDATE: also, I have discovered that the problem only happens when i post the link directly in the address bar. but if the component is traversed internally from some other component, then the error doesnt happen. any idea as to why? Any ideas what could be causing a prob only in one invocation?


Solution

  • finally found the issue. since I was using the URL directly, the second invocation (the one throwing error) was executing the useCacheCall() even before the drizzle has initialized properly and setup the connection to ethereum. Putting a </drizzleReactHooks.Initializer> component on my < App / > solved the issue:

    <drizzleReactHooks.Initializer
          error="There was an error."
          loadingContractsAndAccounts="loading contracts & accounts..."
          loadingWeb3="loading web3..."
        >
    <App/>
    </drizzleReactHooks.Initializer>