After building out a handful of Dapps in React, I decided to carve out all the common components and provide them in an NPM package.
Should help get a Dapp up and running quickly so you can focus on your functionality, not wrestling with the blockchain and ethereum network.
A good example and development walkthrough is nifties-vs-nfties.
npm install --save dapparatus
import { Metamask, Gas, ContractLoader, Transactions, Events, Scaler } from "dapparatus"
Looks for injected web3 and provides an interface to the rest of the components. Also displays a nice HUD for users to see what account is logged in, what network they are on, and how much Ethereum they have.
<Metamask
/*config={{requiredNetwork:['Ropsten']}}*/
onUpdate={(state)=>{
console.log("metamask state update:",state)
if(state.web3Provider) {
state.web3 = new Web3(state.web3Provider)
this.setState(state)
}
}}
/>
Keeps track of the best gas price in gwei and delivers it to other components.
<Gas
onUpdate={(state)=>{
console.log("Gas price update:",state)
this.setState(state,()=>{
console.log("GWEI set:",this.state)
})
}}
/>
Displays transactions and blocks as progress bars and provides a tx function to make calling smart contract functions and sending transactions easier and more transparent to the user.
<Transactions
account={account}
gwei={gwei}
web3={web3}
block={block}
avgBlockTime={avgBlockTime}
etherscan={etherscan}
onReady={(state)=>{
//loads in tx() function
// use to send transactions: tx(contracts.YOURCONTRACT.YOURFUNCTION(),GASLIMIT)
console.log("Transactions component is ready:",state)
this.setState(state)
}}
/>
Loads your contracts published from Clevis into this.state.contracts.
<ContractLoader
web3={web3}
require={path => {return require(`${__dirname}/${path}`)}}
onReady={(contracts)=>{
console.log("contracts loaded",contracts)
this.setState({contracts:contracts})
}}
/>
Listens for events and parses down the chain. Use an id field for unique keys so it will only fire the onUpdate function when a new event is detected. Provide a filter object to filter indexed fields.
<Events
contract={contracts.Nifties}
eventName={"Create"}
block={block}
id={"_id"}
filter={{_owner:account}}
onUpdate={(eventData,allEvents)=>{
console.log("EVENT DATA:",eventData)
this.setState({events:allEvents})
}}
/>
Scales components based on a target screen width vs actual screen width. Get your Dapp looking awesome on mobile.
<Scaler config={{origin:"50px 50px",adjustedZoom:1.3}}>
<img style={{position:"absolute",left:10,top:10,maxHeight:120,margin:10}} src={titleImage}/>
</Scaler>