3

I am new to React and don't know where I should put the code to .watch() for Solidity events.

Right now, I the code in a member function of my main App class. As is, I am successfully capturing events emitted by my contract ... but only when the page loads.

My goal is to subscribe to events so that I can log them as soon as they occur, but with React, I'm not sure where the proper place to put that code would be:

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;
1
let event = contractInstance.event()
event.watch(callback)

Working example in an onClick function:

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

This is in Vuejs but it's very similar: https://itnext.io/create-your-first-ethereum-dapp-with-web3-and-vue-js-part-3-dc4f82fba4b4

In this example I have defined a reactive variable in the data() property, when the event fires this variable will update and the dom will re-render with the event.

  • Looking at your snippet, I'm guessing this returns to you every single Won() event from all blocks? I have set something like this up, but each time I trigger the method, it returns back the full history of that event. Will have to filter these results. Thanks! – Ryan Miller Mar 21 '18 at 1:35
  • Since I'm only listening for events when sending a transaction it only returns the event for the user sending the transaction. At least , I haven't tested it with multiple tx being sent in the same block to the contract. – Nico Mar 21 '18 at 1:49
  • You can probably also use web3.eth.filter('latest', ... ) , that watchest the last block. – Nico Mar 21 '18 at 1:50
0

You can use componentDidMount inside your React component:

class MyCPT extends React.Component {
  componentDidMount() {
    // your code here
  }
}

componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.

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

  • Thanks! I did that. But unfortunately I'm only seeing the events come in when I refresh the page. How would I have this subscribe to all events as they come in live? – Ryan Miller Mar 20 '18 at 15:08
  • can you update your post with the new code of your component ? – mirg Mar 20 '18 at 15:16
  • hi @mirg , i have updated my original post with my code (tried to remove unnecessary parts). – Ryan Miller Mar 20 '18 at 21:30
  • contributedEvent is not defined and the syntax is wrong. myContractInstance.MyEvent(callback); is the right syntax. In your case the contract instance is attendanceDataInstance. github.com/ethereum/wiki/wiki/JavaScript-API#contract-events or ethereum.stackexchange.com/questions/42539/… – mirg Mar 21 '18 at 2:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.