使用 Solana Integration 时出现 React hooks 错误

问题描述 投票:0回答:1

我不是前端开发人员,但目前正在尝试使用可用的 Solana Dapp 支架为 Solana 应用程序构建测试前端。但是,我有以下错误:

“账号采集失败!hook调用无效。只能调用hook 函数组件主体内部。这可能发生在一个人身上 原因如下: 1. 您的版本可能不匹配 React 和渲染器(例如 React DOM) 2. 你可能会破坏 Hooks 规则 3. 你可能有不止一份 React 副本 相同的应用程序 请参阅 https://reactjs.org/link/invalid-hook-call 了解提示 关于如何调试和解决这个问题。”

let PROGRAM_ABI; // Define PROGRAM_ABI variable
    
// Fetch the JSON file using fetch API
fetch('../deployment_data/xxx.json')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json(); // Parse the JSON response
  })
  .then(data => {
    // Assign the parsed JSON data to PROGRAM_ABI
    PROGRAM_ABI = data;
    console.log('PROGRAM_ABI:', PROGRAM_ABI);
  })
  .catch(error => {
    console.error('Error fetching JSON:', error);
  });
export const GetContractAccounts: FC = () => {
  const { connection } = useConnection();
  const { publicKey } = useWallet();
  const { getUserSOLBalance } = useUserSOLBalanceStore();

  const onClick = useCallback(async () => {
    if (!publicKey) {
      console.log('error', 'Wallet not connected!');
      notify({
        type: 'error',
        message: 'error',
        description: 'Wallet not connected!'
      });
      return;
    }

    let signature: TransactionSignature = '';

    try {
      const secret = [my private key]; // Replace with your secret
           
      const fromKeypair = Keypair.fromSecretKey(new Uint8Array(secret));

      const communityId = 123;
      const communityName = "MyCommunity";
      const parentCommunityId = 456;
      const tags = [];
      const chainID = 789;
      const chainName = "Solana";

      const dataArray = [
        communityId.toString(),
        communityName.toString(),
        parentCommunityId.toString(),
        tags.join(','),
        chainID.toString(),
        chainName.toString()
      ];
      const concatenatedData = dataArray.join('');

      const { publicKey, signTransaction, signAllTransactions } = useWallet();
      const signerWallet = {
        publicKey: publicKey,
        signTransaction: signTransaction,
        signAllTransactions: signAllTransactions,
      };
      const provider = new anchor.Provider(
        connection,
        signerWallet,
        { commitment: "processed" }
      );

      const votingProgram = new PublicKey('my public key');
      const program = new anchor.Program(
        PROGRAM_ABI,
        votingProgram,
        provider
      );
      const accounts = await program
        .account
        .votingProgram
        .fetch(fromKeypair.publicKey)
      console.log(accounts)
    } catch (error: any) {
      notify({
        type: 'error',
        message: `Account gathering failed!`,
        description: error?.message,
        txid: signature
      });
      console.log(
        'error',
        `Account gathering failed! ${error?.message}`,
        signature
      );
    }
  }, [publicKey, connection]);

  return (
    <div className="flex flex-row justify-center">
      <div className="relative group items-center">
        <div
          className="m-1 absolute -inset-0.5 bg-gradient-to-r 
            from-indigo-500 to-fuchsia-500 rounded-lg blur opacity-20 
            group-hover:opacity-100 transition duration-1000
            group-hover:duration-200 animate-tilt"
        ></div>
        <button
          className="px-8 m-2 btn animate-pulse bg-gradient-to-br
            from-indigo-500 to-fuchsia-500 hover:from-white
            hover:to-purple-300 text-black"
          onClick={onClick}
        >
          <span>Contract Accounts</span>
        </button>
      </div>
    </div>
  );
};
reactjs typescript react-native react-hooks solana
1个回答
0
投票

onClick
回调调用
useWallet
,这违反了React的Hooks规则之一。你不应该在嵌套函数/回调/等中调用 React hooks。

使用外部作用域中的

useWallet
访问
publicKey
signTransaction
signAllTransactions
值,确保这些值正确添加到
useCallback
钩子的依赖项数组中。

export const GetContractAccounts: FC = () => {
  const { connection } = useConnection();
  const {
    publicKey,
    signTransaction,
    signAllTransactions
  } = useWallet();

  ...

  const onClick = useCallback(async () => {
    if (!publicKey) {
      ...
    }

    ...

    try {
      ...

      const signerWallet = {
        publicKey,
        signTransaction,
        signAllTransactions,
      };

      const provider = new anchor.Provider(
        connection,
        signerWallet,
        { commitment: "processed" }
      );

      ...
    } catch (error: any) {
      ...
    }
  }, [publicKey, signTransaction, signAllTransactions, connection]);

  return (
    <div className="flex flex-row justify-center">
      <div className="relative group items-center">
        <div className="....." />
        <button className="...." onClick={onClick}>
          <span>Contract Accounts</span>
        </button>
      </div>
    </div>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.