为啥我无法使用 Next.js 的 getInitialProps 获取我的 Metamask 帐户地址?

Posted

技术标签:

【中文标题】为啥我无法使用 Next.js 的 getInitialProps 获取我的 Metamask 帐户地址?【英文标题】:Why can't I fetch my Metamask account address with Next.js's getInitialProps?为什么我无法使用 Next.js 的 getInitialProps 获取我的 Metamask 帐户地址? 【发布时间】:2019-06-23 07:21:02 【问题描述】:

我正在使用 Next.js 在我的 Ethereum 应用程序中实现服务器端渲染,但是 我无法获取我的 Metamask 地址以将其显示在我的索引导航栏的右上角。 .js 文件。目前,我的 getInitialProps() 函数返回一个空数组。谁能帮我让它工作?

我正在使用 web3 v1.0.0-beta.35 我已登录 Metamask(使用 v 5.3.1) 我正在使用 web3.eth.getAccounts() 从 Metamask 中获取帐户 我已根据其breaking changes 授予该应用访问 Metamask 帐户的权限。

在一些情况下,地址确实会在刷新时弹出,但大多数情况下它不起作用。

这里是这个项目的 repo:https://github.com/jviray/buidl-box

下面是我的 index.js 文件的代码,其中包含给我带来问题的组件。该地址应显示在导航栏的右上角,其中显示 this.props.accounts[0] 。

import React,  Component  from 'react';
import Head from 'next/head';
import  Jumbotron, Button  from 'react-bootstrap/lib';
import web3 from '../ethereum/web3';

class Welcome extends React.Component 
  static async getInitialProps() 
    const accounts = await web3.eth.getAccounts();

    return  accounts ;
  

  render() 
    const jumbostyle = 
      textAlign: 'center',
      marginTop: '30px'
    ;

    return (
      <div>
        <Head>
          <title>BUIDL</title>
          <meta
            name="viewport"
            content="initial-scale=1.0, width=device-width"
          />
          /* -- Latest compiled and minified CSS */
          <link
            rel="stylesheet"
            href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
            integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
            crossorigin="anonymous"
          />
        </Head>
        /* NAVBAR */
        <nav className="navbar navbar-inverse navbar-fixed-top">
          <div className="container">
            <div className="navbar-header">
              <a href="#" className="navbar-brand">
                BUIDL
              </a>
            </div>

            /* NAVBAR ITEMS */
            <ul className="nav navbar-nav navbar-right">
              <li className="navbar-brand">this.props.accounts[0]</li>
            </ul>
          </div>
        </nav>
        <Jumbotron>
          <div className="container" style=jumbostyle>
            <h1>Welcome, Ethereum Devs!</h1>
            <p>
              As a community we need to start building new and powerful
              applications that truly add value.
            </p>
            <p>
              <a href="https://www.coindesk.com/dont-hodl-buidl-blockchain-tech-will-add-value-2018">
                <Button bsStyle="primary">Learn more</Button>
              </a>
            </p>
          </div>
        </Jumbotron>;
      </div>
    );
  


export default Welcome;

有趣的是,如果我添加组件状态并使用 React 的“async componentDidMount()”到 setState() 与获取的帐户,我可以让它在刷新后一致地工作而不会出现问题。强>

但同样的目标是使用 getInitialprops 在服务器端获取帐户,但我无法让它工作。

这是我使用“async componentDidMount()”时有效的代码

import React,  Component  from 'react';
import Head from 'next/head';
import  Jumbotron, Button  from 'react-bootstrap/lib';
import web3 from '../ethereum/web3';

class Welcome extends React.Component 
  state = 
    accountAddress: ''
  ;

  async componentDidMount() 
    const accounts = await web3.eth.getAccounts();

    this.setState(
      accountAddress: accounts[0]
    );
  

  render() 
    const jumbostyle = 
      textAlign: 'center',
      marginTop: '30px'
    ;

    return (
      <div>
        <Head>
          <title>BUIDL</title>
          <meta
            name="viewport"
            content="initial-scale=1.0, width=device-width"
          />
          /* -- Latest compiled and minified CSS */
          <link
            rel="stylesheet"
            href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
            integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
            crossorigin="anonymous"
          />
        </Head>
        /* NAVBAR */
        <nav className="navbar navbar-inverse navbar-fixed-top">
          <div className="container">
            <div className="navbar-header">
              <a href="#" className="navbar-brand">
                BUIDL
              </a>
            </div>

            /* NAVBAR ITEMS */
            <ul className="nav navbar-nav navbar-right">
              <li className="navbar-brand">this.state.accountAddress</li>
            </ul>
          </div>
        </nav>
        <Jumbotron>
          <div className="container" style=jumbostyle>
            <h1>Welcome, Ethereum Devs!</h1>
            <p>
              As a community we need to start building new and powerful
              applications that truly add value.
            </p>
            <p>
              <a href="https://www.coindesk.com/dont-hodl-buidl-blockchain-tech-will-add-value-2018">
                <Button bsStyle="primary">Learn more</Button>
              </a>
            </p>
          </div>
        </Jumbotron>;
      </div>
    );
  


export default Welcome;

如果有人能解决这个问题,那就太棒了,但我也希望能就可能的问题提供意见(异步/等待代码、Next.js、web3、React 等)。谢谢!!

【问题讨论】:

【参考方案1】:

我查看了你的仓库。

在执行 getInitialProps 时首次访问浏览器新选​​项卡中的页面,使用的是 web3 提供程序的 infura 版本。它无权访问您浏览器的元掩码。

但是,如果您从另一个页面访问同一页面,则将使用 web3 提供程序的元掩码版本。所以它有帐户信息。

假设您有 2 条路线:/home and /list/home 页面中您有

static async getInitialProps() 
    const accounts = await web3.eth.getAccounts();
 

如果您在浏览器的新标签页中访问域/主页,由于上述原因,您将得到一个空数组。但是,如果您从同一浏览器选项卡中的域/列表访问域/主页,您将获得您的元掩码帐户信息。

【讨论】:

以上是关于为啥我无法使用 Next.js 的 getInitialProps 获取我的 Metamask 帐户地址?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们在 MongoDB 的 Next.js 应用程序中有 api 文件夹?

为啥 Carousel 不接受 Next.js 图片?

为啥我的 Next JS 性能分数在 web.dev 中如此不一致?

为啥切换语言环境时我的会话没有加载?

在 Next.js 中,为啥要静态渲染? _document.js 包括 getInitialProps

使用 next.js 调整窗口大小时无法居中我的图像