有没有办法编写可以注入组件的自定义反应挂钩?

Is there a way to write a custom react hook that can injected into a component?

我有一个项目在使用 npm run dev 时 运行s 是 package.json 文件中的 next dev 因为我们使用 React 框架 Next.js。当我 运行 npm run buildnext build 时,React Hooks 出现多个错误。

npm 运行 构建中的示例错误:

36:23  Error: React Hook "useEtherBalance" is called in function "connectClick" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter.  react-hooks/rules-of-hooks

从我目前对这个问题的研究来看,高阶组件似乎可以解决项目面临的问题。本质上,我希望将自定义挂钩注入构成项目的组件。

文件结构:

当前代码:

import React, { useEffect, useState } from 'react';
import Router from 'next/router';
import { Button } from 'reactstrap';
import styles from '../../styles/TopNavbar.module.css';
import '../../public/logo_P_1.png';
import MetaMaskOnboarding from '@metamask/onboarding';
import { useEtherBalance, useEthers } from '@usedapp/core';

export default function TopNavbar() {
    const [buttonText, setButtonText] = useState("Connect");
    const [buttonDisabled, setButtonDisabled] = useState(false);
    const [connected, setConnected] = useState(false);
    const { activateBrowserWallet, account } = useEthers();
    const balance = useEtherBalance(account);

    useEffect(() => {
        initialize();
    })

    const connectClick = async () => {
        if (buttonText === "Connect") {
            activateBrowserWallet();
            setConnected(true);
        } else if (buttonText === "Click here to install MetaMask!") {
            setButtonText("Onboarding in progress");
            setButtonDisabled(true);
            const forwarderOrigin = 'http://localhost:9010';
            // Creating a new MetaMask onboarding object
            const onboarding = new MetaMaskOnboarding({ forwarderOrigin });
            // Starts onboarding for our und user
            onboarding.startOnboarding();
        } else if (buttonText === "Sign In") {
            const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
            const accountNum = accounts[0];
            // TODO: Getting the Ether balance causes issues
            balance = useEtherBalance(accountNum);
        }
    }

    const initialize = () => {
        // Checking the ethereum binding on the window object to see if it's installed
        const isMetaMaskInstalled = () => {
            const { ethereum } = window;
            return (ethereum && ethereum.isMetaMask);
        }
        const MetaMaskClientCheck = () => {
            // If it isn't installed we ask the user to click to install it
            if (!isMetaMaskInstalled()) {
                setButtonText('Click here to install MetaMask!');
                setButtonDisabled(false);
            } else {
                // If it is installed we change our button text
                setButtonText('Sign In');
                setButtonDisabled(false);
            }
        };
        MetaMaskClientCheck();
    }

    return (
        <div className={styles.topNavbar}>
            <div className={styles.topbarWrapper}>
                <div>
                    <!-- Logo placeholder -->
                </div>
                <div className={styles.topbarRight}>
                    {(!!account && !!balance) ?
                        // <p className={styles.walletBalance}>Wallet Balance {formatUnits(balance.toString())}ETH</p> :
                        <Button className={styles.connectButton} onClick={() => Router.push('/home')}>Continue</Button> :
                        <Button disabled={buttonDisabled} className={styles.connectButton} onClick={() => connectClick()}>{buttonText}</Button>
                    }
                </div>
            </div>
        </div>
    )
}

错误信息

删除连接点击函数中的调用钩子,

删除它

balance = useEtherBalance(accountNum);

正确的函数形式:

const connectClick = async () => {
        if (buttonText === "Connect") {
            activateBrowserWallet();
            setConnected(true);
        } else if (buttonText === "Click here to install MetaMask!") {
            setButtonText("Onboarding in progress");
            setButtonDisabled(true);
            const forwarderOrigin = 'http://localhost:9010';
            // Creating a new MetaMask onboarding object
            const onboarding = new MetaMaskOnboarding({ forwarderOrigin });
            // Starts onboarding for our und user
            onboarding.startOnboarding();
        } else if (buttonText === "Sign In") {
            const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
            const accountNum = accounts[0];
            // TODO: Getting the Ether balance causes issues
        }
    }