Search code examples
javascriptreactjstypescriptthisarrow-functions

Function is not calling on onclick event in React


Here I simply want to call a walletconnect function when I click on the button. but it is not calling any function. please correct me if I'm wrong somewhere.

App.tsx

import * as React from 'react';
import WalletConnect from "@walletconnect/client";
import QRCodeModal from "@walletconnect/qrcode-modal";


class App extends React.Component<any, any> {

  constructor(props:any) {
    super(props)
    this.state = {
      address: ''

    }
    
    const connector = new WalletConnect({
      bridge: "https://bridge.walletconnect.org", // Required
      qrcodeModal: QRCodeModal,
    });
  }

  walletConnectFunc = async () => {
    const connector = new WalletConnect({
      bridge: "https://bridge.walletconnect.org", // Required
      qrcodeModal: QRCodeModal,
    });
    if (connector.connected) {
      alert("already connected")
      return
    }
    connector.createSession();
    connector.on("connect", async (error, payload) => {
      console.log("connect")
      if (error) {
        throw error;
      }

      // Get provided accounts and chainId
      const { accounts, chainId } = payload.params[0];
      console.log("connect account", accounts)
      console.log("chainid account", chainId)

      const obj = {
        "address": accounts[0],

      }
      this.setState({ address: obj.address })
      console.log(this.state.address)
      alert(this.state.address)
    })


  }
  render() {
    return (
      <div className="App">
          <div>
            <button className="btn btn-primary my-4" type="button" onClick={() => this.walletConnectFunc()}>WalletConnect</button>
          </div>
      </div>
    );
  }
}

export default App;

If more code is required then tell me in a comment section. I will update my question with that information.


Solution

  • Firstly, you should remove the redundant async keyword, Just walletConnectFunc() is enough. Simply because, inside your function do not call any await keyword, So that does not make sense.

    Secondly, You just listen to event onClick like onClick={this.walletConnectFunc} to avoid creating an extra function in the render (As @Zac Anger's recommendation)

    Finally, in case you have to access this inside the function, use arrow function or you can also bind this context like this way (For me, I highly recommend using the third way for the performance aspect)

    In short, Just need to use arrow function when using context. enter image description here

    import React, { Component } from "react";
    import "./styles.css";
    
    export default class extends Component {
      constructor(props) {
        super(props);
        this.state = {
          address: ""
        };
    
        this.walletConnectFuncAsync = this.walletConnectFuncAsync.bind(this);
      }
    
      async walletConnectFuncAsync() {
        await this.sleep(1000);
      }
    
      sleep(ms) {
        return new Promise((resolve) => {
          setTimeout(() => alert("Woke up after " + ms + "ms"), ms);
        });
      }
    
      walletConnectFunc() {
        alert(123);
      }
    
      render() {
        return (
          <div className="App">
            <div>
              <button
                className="btn btn-primary my-4"
                type="button"
                onClick={this.walletConnectFunc}
              >
                WalletConnect
              </button>
              <button
                className="btn btn-primary my-4"
                type="button"
                onClick={this.walletConnectFuncAsync}
              >
                WalletConnect_Async
              </button>
            </div>
          </div>
        );
      }
    }
    

    Demo on Codesandbox here