Web3js

如何使用 Web3-react 保持 MetaMask 與 UI 的持久連接?

  • December 15, 2021

我正在使用 web3-react,但我無法弄清楚如何在瀏覽器刷新時保持與 MetaMask 錢包的連接。

這是程式碼:

// define the injectedConnectors

const injectedConnector = new InjectedConnector({
 supportedChainIds: [
   1, // Mainet
   3, // Ropsten
   4, // Rinkeby
   5, // Goerli
   42, // Kovan
 ],
})

const { chainId, account, activate, active } = useWeb3React()
// activate the wallet
activate(injectedConnector)
console.log(account)
// all good. 

到目前為止一切正常,我啟動了我的 MetaMask 錢包,並正確記錄了帳戶,並且活動變數是一個變為 true 的布爾值。問題是,當我刷新頁面時,活動變為 false,並且我失去了 UI 與 MetaMask 錢包之間的連接。當然,將活動保存到瀏覽器中不會改變任何內容,因為連接依賴於活動布爾值。文件缺少此類資訊。任何幫助將不勝感激。

它被稱為“渴望連接”

  • 將 connectorId 儲存在本地儲存中
  • 在頁面載入時,使用該鍵從“@web3-react/core”呼叫啟動

-> 帳戶應該更新。

參考:https ://github.com/pancakeswap/pancake-frontend/blob/develop/src/hooks/useEagerConnect.ts

它實際上非常簡單。您可以將連接地址儲存在本地儲存中,當使用者點擊斷開連接按鈕時,然後從本地儲存中刪除該地址。基本上我們使用的條件是,如果本地儲存中有一個帳戶,那麼我們在載入時連接,如果沒有,那麼我們必須手動點擊連接按鈕。考慮下面的程式碼。請注意,理想情況下,您應該將邏輯編寫為鉤子並在主應用程序中使用鉤子,然後將從 useWeb3React() 返回的“活動”狀態傳遞給道具。但出於本範例的目的,我只是將連接邏輯保存在一個文件中,以使其更易於閱讀

import React, { useState, useEffect } from 'react';
import Web3 from 'web3';
import detectEthereumProvider from '@metamask/detect-provider';
import { useWeb3React } from "@web3-react/core"
import { InjectedConnector } from '@web3-react/injected-connector'

//declare supportated chains
export const injected = new InjectedConnector({
 supportedChainIds: [1, 3, 4, 5, 42, 1337, 43114],
})


export default function connButton() {

var web3;
var accounts;
var connected

const [loading, setLoading] = useState(false)

//here we can destructure out various things from web3React such as
//active (which is true if the user is connected and false otherwise)
//activate and deactiveate which we use to instansiate and break the users
//connection
const { active, account, library, connector, activate, deactivate } = useWeb3React()

//set up an elemnt in local storage that we use to hold the connected account
var acc = localStorage.getItem("account")



//function that initialises web3.js
const connectWalletHandler = () => {
   if (window.ethereum && window.ethereum.isMetaMask) {
       console.log('MetaMask Here!');
       web3 = new Web3(window.ethereum);

       window.ethereum.request({ method: 'eth_requestAccounts'})
       
   } else {
       console.log('Need to install MetaMask');
       // setErrorMessage('Please install MetaMask browser extension to interact');
   }
   console.log(web3.eth.currentProvider)
}

//function that is called on page load if and only if their exists and
//item for the user accoun tin local storage
async function connectOnLoad() {

    try {
       
       //here we use activate to create the connection
       await activate(injected)
       connected = true
     } catch (ex) {
       console.log(ex)
     }

     //we use web3.eth to get the accounts to store it in local storage
     var accounts1 = await web3.eth.getAccounts();
     acc = localStorage.setItem("account", accounts1);
}

//here we use a useEffect so that on page load we can check if there is
//an account in local storage. if there is we call the connect onLoad func
//above which allows us to presist the connection and i also call connectWalletHandler
which sets up web3.js so we can call web3.eth.getAccounts()
useEffect(() => {

       
   if (acc != null) {
   connectOnLoad()
   }
   connectWalletHandler()
}, [])


//however in the case where there is no item in local storage we use this
//function to connect which is called when we click the connect button. its
//essentially the same but we check if local storage is null if it is we activate
//if its not then we disconnect. And when we disconnect we remove the acccount from local storage
async function connectOnClick() {
   
   if (localStorage.getItem("account") == null) {

       setLoading(true);
       try {
           await activate(injected)
           connected = true
       } catch (ex) {
           console.log(ex)
       }
       // window.location.reload();
       var accounts1 = await web3.eth.getAccounts();
       console.log(accounts1)
       acc = localStorage.setItem("account", accounts1);
       console.log(acc)
       setTimeout(function(){
           setLoading(false)
        }, 1600);//wait 2 seconds
       
   } else {

       disconnect();
       connected = false
   }

}

async function disconnect() {
   try {
   deactivate()
   localStorage.removeItem("account");
   } catch (ex) {
   console.log(ex)
   }
}



return (
 
   //remember the active boolean from useReactWeb3() stores a bool
   //depending on if the user is or is not connected there for we can 
   //use this as a conditon to render the button saying "Connect Wallet"
   or displaying their address as the text.
   <div>
         {active ? <button onClick={connectOnClick}>{account.substring(0, 6)}...{account.substring(account.length - 4)}</button> : <button onClick={connectOnClick}>Connect Wallet</button>}
   </div>
 );
}

然後在您的 app.js 中記住將整個應用程序包裝在標籤中。請記住,這意味著您還需要將 web3React 導入到您的 app.js 中

引用自:https://ethereum.stackexchange.com/questions/103355