Web3js
如何使用 Web3-react 保持 MetaMask 與 UI 的持久連接?
我正在使用 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 中