是否可以通过使用 HOC(高阶组件)在类组件中使用 React Hooks?

Sat*_*ill 2 typescript reactjs react-hooks wallet-connect

我可以在类组件中使用功能组件吗?我将调用从类组件中的功能组件中提取的函数。但它给出了如下错误。

未处理的拒绝(错误):无效的挂钩调用。钩子只能在函数组件的主体内部调用。出现这种情况可能是由于以下原因之一

所以我尝试在功能组件中调用它,但即使在功能组件中,我也遇到了与在类组件中调用它时相同的错误。

功能组件

import React, { useEffect } from 'react';
import { UseWalletProvider, useWallet } from 'use-wallet';
import { providers } from 'ethers';

export function App() {
  useEffect(() => {
    async function GetBlockId() {
      const wallet = useWallet();
      console.log(wallet); // =====> This is not displaying.
      const { ethereum, connect } = wallet;
      const ethersProvider = new providers.Web3Provider(ethereum);
      const { blockNumber } = await ethersProvider.getTransaction(hash);
      console.log(blockNumber);
    };
    GetBlockId()
  }, []);

  return <div>
    <h1>{wallet}</h1>
  </div>
}
Run Code Online (Sandbox Code Playgroud)

类组件

import React, { Component } from 'react'
import { GetBlockId } from './util';   // =====>> I hope to get result from here.
import { hash } from './hash'

export default class App extends Component {
    constructor(props) {
        super(props)
    }
    componentDidMount(): void {
        const blockNumber: any = GetBlockId(hash);
        console.log(blockNumber);
    }
    render() {
        return (
            <div>
                <h1>test</h1>
            </div>
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

实用程序.tsx

import React, { useEffect } from 'react';
import { UseWalletProvider, useWallet } from 'use-wallet';
import { providers } from 'ethers';
// import { Container } from './styles';

export function GetBlockId() {
  useEffect(() => {
    async function GetBlockId() {
      const wallet = useWallet();
      const { ethereum, connect } = wallet;
      const ethersProvider = new providers.Web3Provider(ethereum);
      const { blockNumber } = await ethersProvider.getTransaction(hash);
      return blockNumber;
    };
    GetBlockId()
  }, []);
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

所以最后我希望在类组件中使用“use-wallet”包。那可能吗?如果是,如何在类组件中使用useWallet钩子?

Dre*_*ese 8

React hooks 仅与 React 函数组件兼容,它们根本不能在类组件中使用。您第一次尝试的问题是您尝试在回调中调用 React hook,这违反了 Hook 规则之一。

\n

钩子规则

\n
\n

仅在顶层调用挂钩

\n

不要\xe2\x80\x99t 在循环、条件或嵌套函数内调用 Hooks。\n相反,请始终在 React 函数的顶层、\n在任何早期返回之前使用 Hooks。通过遵循此规则,您可以确保每次组件渲染时\n以相同的顺序调用 Hooks。\n这\n\xe2\x80\x99s 允许 React 在多个 useState 和 useEffect 调用之间\n正确保留 Hooks 的状态。(如果您\xe2\x80\x99很好奇,\n我们\xe2\x80\x99将在下面深入解释这一点。)

\n

仅从 React 函数调用 Hook

\n

不要\xe2\x80\x99t 从常规 JavaScript 函数调用 Hook。相反,您可以:

\n
    \n
  • \xe2\x9c\x85 从 React 函数组件调用 Hooks。
  • \n
  • \xe2\x9c\x85 从自定义 Hook 调用 Hook(我们\xe2\x80\x99 将在下一页了解它们)。
  • \n
\n

通过遵循此规则,您可以确保组件中的所有状态逻辑从其源代码中清晰可见。

\n
\n

您的代码正在调用useWallet传递给挂钩的回调函数useEffect。请注意,这与调用另一个钩子的自定义钩子不同。

\n

useWallet钩子调用移出到函数组件主体中。这将关闭wallet渲染范围中的值,并将在钩子回调中可用/可访问useEffect。我假设您仍然只希望/需要useEffect在组件安装时运行一次钩子,所以我将不理会这方面。

\n
import React, { useEffect } from \'react\';\nimport { UseWalletProvider, useWallet } from \'use-wallet\';\nimport { providers } from \'ethers\';\n\nexport function App() {\n  const wallet = useWallet();\n\n  useEffect(() => {\n    console.log(wallet);\n    const { ethereum, connect } = wallet;\n\n    async function GetBlockId() {          \n      const ethersProvider = new providers.Web3Provider(ethereum);\n      const { blockNumber } = await ethersProvider.getTransaction(hash);\n      console.log(blockNumber);\n    };\n\n    GetBlockId();\n  }, []);\n\n  return (\n    <div>\n      <h1>{wallet}</h1>\n    </div>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

更新

\n

要将钩子与类组件一起使用,我建议创建一个可以使用它并将值作为 propuseWallet传递的高阶组件。wallet

\n

例子:

\n
const withWallet = Component => props => {\n  const wallet = useWallet();\n  return <Component {...props} wallet={wallet} />;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

装饰类组件并通过以下方式访问this.props.wallet

\n
class App extends Component {\n  constructor(props) {\n    super(props)\n  }\n  componentDidMount(): void {\n    const { ethereum, connect } = this.props.wallet;\n\n    ...\n  }\n  render() {\n    return (\n      ...\n    );\n  }\n}\n\nexport default withWallet(App);\n
Run Code Online (Sandbox Code Playgroud)\n