Auf Ereignisse in einer React DApp lauschen

Ich bin neu bei React und weiß nicht, wo ich den Code .watch()für Solidity-Events ablegen soll.

Im Moment habe ich den Code in einer Member-Funktion meiner Haupt-App-Klasse. So wie es ist, erfasse ich erfolgreich Ereignisse, die von meinem Vertrag ausgegeben werden ... aber nur, wenn die Seite geladen wird.

Mein Ziel ist es, Ereignisse zu abonnieren, damit ich sie protokollieren kann, sobald sie auftreten, aber bei React bin ich mir nicht sicher, wo der richtige Ort für diesen Code wäre:

import React, { Component } from 'react';
import AttendanceData from '../build/contracts/AttendanceData.json';
import getWeb3 from './utils/getWeb3';


class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      contract: null,
      name: "",
      storageValue: 0,
      eventId: 0,
      currentEventValue: 0,
      hasContributed: false,
      isLoggedIn: false,
      loggedInAddress: "",
      web3: null
    }
  }


  componentDidMount() {
    getWeb3
    .then(results => {
        this.setState({
            web3: results.web3
        })
        const contract = require('truffle-contract');
        const attendanceData = contract(AttendanceData);
        attendanceData.setProvider(this.state.web3.currentProvider);
        this.setState({contract: attendanceData});
        attendanceData.Contributed({}, {fromBlock: 1, toBlock: 'latest'});
        contributedEvent.watch(function(error, result) {
            if(!error){
                console.log("Event captured:", result);
            }
            else{
                console.log("Error capturing event:", error);
            }
        });
    })
    .catch(() => {
      console.log('Error finding web3.')
    })
  }

  contribute() {
    const attendanceData = this.state.contract;

    // Declaring this for later so we can chain functions on AttendanceData.
    var attendanceDataInstance;

    // Get accounts.
    this.state.web3.eth.getAccounts((error, accounts) => {
      attendanceData.deployed().then((instance) => {
        attendanceDataInstance = instance;
        // Stores a given value, 5 by default.
        return attendanceDataInstance.contribute({value: this.state.web3.toWei(this.state.amountToContribute, 'ether'), gasPrice: 2000000000, gas: 300000, from: accounts[0]})
      }).then((result) => {
        console.log("Was successful: "+result);
      }).catch((err) => {
        console.log("Failed with error: " + err);
      });
    })
  }

  render() {
    return (
      <div className="App">
        <button onClick={this.contribute}>CONTRIBUTE!</button>
      </div>
    );
  }
}

export default App;

Antworten (2)

let event = contractInstance.event()
event.watch(callback)

Arbeitsbeispiel in einer onClick-Funktion:

https://gist.github.com/kyriediculous/13efccc780a9c180b37f4c27fe696bb8#file-methods-js

Dies ist in Vuejs, aber es ist sehr ähnlich: https://itnext.io/create-your-first-ethereum-dapp-with-web3-and-vue-js-part-3-dc4f82fba4b4

In diesem Beispiel habe ich eine reaktive Variable in der Eigenschaft data() definiert, wenn das Ereignis ausgelöst wird, wird diese Variable aktualisiert und der Dom wird mit dem Ereignis neu gerendert.

Wenn ich mir Ihr Snippet ansehe, schätze ich, dass dies jedes einzelne Won()-Ereignis aus allen Blöcken an Sie zurückgibt? Ich habe so etwas eingerichtet, aber jedes Mal, wenn ich die Methode auslöse, gibt sie den vollständigen Verlauf dieses Ereignisses zurück. Diese Ergebnisse müssen gefiltert werden. Vielen Dank!
Da ich beim Senden einer Transaktion nur auf Ereignisse lausche, gibt es nur das Ereignis für den Benutzer zurück, der die Transaktion sendet. Zumindest habe ich es nicht mit mehreren TX getestet, die im selben Block an den Vertrag gesendet werden.
Sie können wahrscheinlich auch web3.eth.filter('latest', ... ) verwenden, das den letzten Block überwacht.

Sie können componentDidMountin Ihrer React-Komponente verwenden:

Klasse MyCPT erweitert React.Component {
  KomponenteDidMount() {
    // Ihr Code hier
  }
}

componentDidMount() wird unmittelbar nach dem Mounten einer Komponente aufgerufen. Eine Initialisierung, die DOM-Knoten erfordert, sollte hier stehen. Wenn Sie Daten von einem Remote-Endpunkt laden müssen, ist dies ein guter Ort, um die Netzwerkanforderung zu instanziieren.

https://reactjs.org/docs/react-component.html#componentdidmount

Vielen Dank! Ich habe das gemacht. Aber leider sehe ich die Ereignisse nur, wenn ich die Seite aktualisiere. Wie würde ich alle Ereignisse abonnieren, sobald sie live kommen?
Können Sie Ihren Beitrag mit dem neuen Code Ihrer Komponente aktualisieren?
Hallo @mirg, ich habe meinen ursprünglichen Beitrag mit meinem Code aktualisiert (versucht, unnötige Teile zu entfernen).
contributedEventist nicht definiert und die Syntax ist falsch. myContractInstance.MyEvent(callback);ist die richtige Syntax. In Ihrem Fall ist die Vertragsinstanz attendanceDataInstance. github.com/ethereum/wiki/wiki/JavaScript-API#contract-events oder ethereum.stackexchange.com/questions/42539/…