Home > OS >  React and Easybase - Invalid hook call. Hooks can only be called inside of the body of a function co
React and Easybase - Invalid hook call. Hooks can only be called inside of the body of a function co

Time:01-25

I am trying to use React and Easybase (database). I'm having some issues however.

This is in the SolanaSignature.tsx file.

import { useWallet } from '@solana/wallet-adapter-react';
import bs58 from 'bs58';
import React, { FC, useCallback } from 'react';
import ReactDOM from 'react-dom';
import { sign } from 'tweetnacl';
import AddUser from './mainstorage';


export const SignMessageButton : FC = () => {
    const { publicKey, signMessage } = useWallet();
    
    const onClick = useCallback(async () => {
        try {
            if (!publicKey) throw new Error('Wallet not connected!');
            if (!signMessage) throw new Error('Wallet does not support message signing! Please use a wallet such as Phantom or Solflare! NOTE: Some Ledgers wallets are not supported!');

            const message = new TextEncoder().encode('Omega Protocol - Signature verification for Bold Badgers.');
            const signature = await signMessage(message);
            if (!sign.detached.verify(message, signature, publicKey.toBytes())) throw new Error('Invalid signature!');
            //alert(`Message signature: ${bs58.encode(signature)}`);
          AddUser();

        } catch (error: any) {
            alert(`Signing failed: ${error?.message}`);
        }
    }, [publicKey, signMessage]);
    return signMessage ? (<button className="wallet-adapter-button wallet-adapter-button-trigger shine" onClick={onClick} disabled={!publicKey}>Verify</button>) : null;       
};

and then the mainstorage file:

import { useEffect } from 'react';
import { useEasybase } from 'easybase-react';

const AddUser = () => {
  const { db } = useEasybase();

  useEffect(() => {
    db('OMEGABB').insert({ walletid: "test", discordid: "test", signature: "test", valid: false, lastvalid: new Date() }).one()
      .then(() => console.log("Success!"));
  }, [])

  return (
    {/* ... */}
  );
}

export default AddUser;

What is happening however when I click the button is that it comes up with a warning: Hooks can only be called inside the body of a function component.

This does work in the initial index file (aka the parent file) but does not work here. Right now this is only a dummy/test but trying to get it writing to the database.

Thanks!

CodePudding user response:

As per React's documentation:

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns.

Currently, you're attempting to call a hook inside the onClick handler - AddUser is a custom hook since it also uses hooks and the better name for it should be useAddUser.

I suggest to make some improvements by returning a function from your custom hook that you can call to add a new user, e.g.:

export const useAddUser = () => {
  const {db} = useEasybase()

  const addUser = React.useCallback(() => {
    db('OMEGABB')
      .insert(/*...*/)
      .then(/*...*/)
      .catch(/*...*/)
  }, [db])

  return {
    addUser,
    /*...*/
  }
}

Then, you can use useAddUser in the following way:

const {useAddUser} from './mainstorage'

const SignMessageButton: FC = () => {
  const {publicKey, signMessage} = useWallet()
  const {addUser} = useAddUser();

  const onClick = React.useCallback(
    async () => {
      try {
        // ...
        addUser()
      } catch (error) {/*...*/}
    }, 
    [publicKey, signMessage, addUser]
  )

  /*...*/
}
  •  Tags:  
  • Related