0

I am making a Fresh app (which is a next-gen web framework that works with Deno). I have an island designed to connect to Metamask. This is the code:
Metamask.tsx:

/** @jsx h */
import { h } from "preact";
import { useState, useEffect } from "preact/hooks";
import { tw } from "@twind";

import { ethers, providers } from "ethers";

export default function Metamask() {
    const [connected, setConnected] = useState(true);
    const [provider, setProvider] = useState(null);
    useEffect(() => {
        async function checkConnection(provider) {
            const addresses = await provider.listAccounts();
            if (addresses.length) {
                setConnected(true);
            } else {
                setConnected(false);
            }
            console.log('useEffect ran')
        }
        const isProviderNull = new Promise((resolve, reject) => {
            if (provider == null) {
                resolve(true);
            }
            else {
                resolve(false);
            }
        })
        function switchSetProvidr() {
            isProviderNull.then(async (result) => {
                if (result) {
                    setProvider(new ethers.providers.Web3Provider(window.ethereum));
                    console.log(provider);
                    await checkConnection(provider);
                }
                else {
                    await checkConnection(provider);
                }
                console.log(result);
            })
        }
        switchSetProvidr()
    }, []);

    async function signIn() {
        try {
            const provider = new providers.Web3Provider(window.ethereum);
            const accounts = await provider.send("eth_requestAccounts", []);
            setConnected(true);
        } catch (err) {
            console.log("error: ", err);
        }
    }

    return (
        <header class={tw`bg-gray-900`}>
            <div class={tw`max-w-screen-xl px-4 mx-auto sm:px-6 lg:px-8`}>
                <div class={tw`flex items-center justify-between h-16`}>
                    <div class={tw`flex items-center gap-4`}>
                        <div class={tw`sm:gap-4 sm:flex`}>
                            {connected ? (
                                <div
                                    class={tw`px-5 py-2.5 text-sm font-medium text-white bg-blue-600 rounded-md shadow disabled:(bg-gray-800 border border-blue-600 opacity-50 cursor-not-allowed)`}>
                                    Connected
                                </div>
                            ) : (
                                <button
                                    onClick={signIn}
                                    class={tw`px-5 py-2.5 text-sm font-medium text-white bg-blue-600 rounded-md shadow disabled:(bg-gray-800 border border-blue-600 opacity-50 cursor-not-allowed)`}>
                                    Connect
                                </button>
                            )}
                        </div>
                    </div>
                </div>
            </div>
        </header>
    );
}

When I run this, the console looks like this:
enter image description here

So the problem is that setProvider(new ethers.providers.Web3Provider(window.ethereum)); isn't working. provider is still null. So how do I get setProvider to work?

Notice that I am importing "preact/hooks" for useState and useEffect.

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
ChristianOConnor
  • 820
  • 7
  • 29
  • 1
    It's working, you just have your console.log in a spot where it isn't useful. That log statement will always log out the old value. Calling `setConnected` does *not* change the value in the local const `connected`, it just asks react to render the component again. When that new render happens, a new local variable will be created, but code in your old render has no access to the next set of variables. If you want to verify that the component rerendered, move your console.log to the body of the component – Nicholas Tower Sep 09 '22 at 00:01
  • 1
    If checkConnection needs the new value, then save the new value to a local variable and use that. `const newProvider = new ethers.providers.Web3Provider(window.ethereum setProvider()); setProvider(newProvider); await checkConnection(newProvider);` – Nicholas Tower Sep 09 '22 at 00:03
  • Thanks! @NicholasTower that second comment you had about setting it as a new variable to access immediately before setting it in setProvider worked. If you make that an answer I'll accept it. – ChristianOConnor Sep 09 '22 at 00:21
  • This question is (rightly) closed as a duplicate, so i cannot post an answer. – Nicholas Tower Sep 09 '22 at 01:04

0 Answers0