diff --git a/test/observables/src/App.js b/test/observables/src/App.js index f8c0b82..bfac40b 100644 --- a/test/observables/src/App.js +++ b/test/observables/src/App.js @@ -1,65 +1,56 @@ -import React from 'react'; -import Phoenix from 'phoenix'; -import { map, scan} from 'rxjs/operators'; -import Web3 from 'web3'; -import withObservables from '@nozbe/with-observables' +import React from "react"; +import Phoenix from "phoenix"; +import Web3 from "web3"; +import EscrowObservator from "./EscrowObservator"; const web3 = new Web3("ws://localhost:8545"); -const Escrow = ({escrow}) => { - console.log("Received new escrow property", escrow); - return <ul><li>{escrow.buyer} {escrow.seller} - <b>EscrowID:{escrow.escrowId}</b></li></ul>; - //return <ul>{props.escrows.map((el, i) => <li key={i}>{el.buyer} {el.seller} {el.escrowId}</li>)}</ul> -}; - -const enhance = withObservables(['escrow'], ({ escrow }) => ({ escrow })); - -const EnhancedEscrow = enhance(Escrow) - class App extends React.Component { - state = { - escrow: null - } + escrowObservable: null + }; - constructor(props){ + constructor(props) { super(props); this.EscrowContract = null; } - componentDidMount(){ - (async () => { + componentDidMount() { + (async () => { let accounts = await web3.eth.getAccounts(); this.EscrowContract = await deployContract(); - await this.EscrowContract.methods.createEscrow(1, accounts[0], accounts[1]).send({from: accounts[0]}) - await this.EscrowContract.methods.createEscrow(1, accounts[1], accounts[2]).send({from: accounts[0]}) - await this.EscrowContract.methods.createEscrow(1, accounts[1], accounts[0]).send({from: accounts[0]}) - await this.EscrowContract.methods.createEscrow(1, accounts[0], accounts[2]).send({from: accounts[0]}) + await this.EscrowContract.methods.createEscrow(1, accounts[0], accounts[1]).send({ from: accounts[0] }); + await this.EscrowContract.methods.createEscrow(1, accounts[1], accounts[2]).send({ from: accounts[0] }); + await this.EscrowContract.methods.createEscrow(1, accounts[1], accounts[0]).send({ from: accounts[0] }); + await this.EscrowContract.methods.createEscrow(1, accounts[0], accounts[2]).send({ from: accounts[0] }); const eventSyncer = new Phoenix(web3.currentProvider); - await eventSyncer.init(); - const replayObj = eventSyncer.trackEvent(this.EscrowContract, 'Created', {filter: {buyer: accounts[0]}, fromBlock: 1}); + this.setState({ - escrow: replayObj.asObservable() + escrowObservable: eventSyncer.trackEvent(this.EscrowContract, "Created", { filter: { buyer: accounts[0] }, fromBlock: 1 }) }); + })(); } createTrx = async () => { let accounts = await web3.eth.getAccounts(); - await this.EscrowContract.methods.createEscrow(Date.now(), accounts[0], accounts[1]).send({from: accounts[0]}) + await this.EscrowContract.methods + .createEscrow(Date.now(), accounts[0], accounts[1]) + .send({ from: accounts[0] }); + }; - } + render() { + const {escrowObservable} = this.state; - render(){ - if(!this.state.escrow) return null; - - return <div> - <button onClick={this.createTrx}>Create Trx</button> - {this.state.escrow && <EnhancedEscrow escrow={this.state.escrow} /> } - </div>; + return ( + <div> + <button onClick={this.createTrx}>Create Trx</button> + <EscrowObservator escrow={escrowObservable} myCustomProperty="Test" /> + </div> + ); } } diff --git a/test/observables/src/EscrowObservator.js b/test/observables/src/EscrowObservator.js new file mode 100644 index 0000000..74bb683 --- /dev/null +++ b/test/observables/src/EscrowObservator.js @@ -0,0 +1,19 @@ +import React from "react"; +import observe from "./observe"; + +const Escrow = props => { + const { escrow, myCustomProperty } = props; + if(!escrow) return <p>Loading...</p>; + return ( + <ul> + <li> + {escrow.buyer} {escrow.seller} - <b>EscrowID:{escrow.escrowId}</b>{" "} + <small>{myCustomProperty}</small> + </li> + </ul> + ); +}; + +const EscrowObservator = observe(Escrow); + +export default EscrowObservator; diff --git a/test/observables/src/observe.js b/test/observables/src/observe.js new file mode 100644 index 0000000..9051c1f --- /dev/null +++ b/test/observables/src/observe.js @@ -0,0 +1,71 @@ +import React, {Component} from 'react'; +import { isObservable } from "rxjs"; + +function observe(WrappedComponent) { + return class extends Component { + state = { + observedValues: {}, + subscriptions: {} + } + + subscribeToProp = prop => { + if(!isObservable(this.props[prop])) return; + + const subscription = this.props[prop].subscribe( + value => { + this.setState({ + observedValues: { + ...this.state.observedValues, + [prop]: value + } + }); + }, + err => { + // TODO: pass the error to the wrapped component + console.err(err); + } + ); + + this.setState({ + subscriptions: { + ...this.state.subscriptions, + [prop]: subscription + } + }); + } + + componentDidMount() { + Object.keys(this.props).forEach(this.subscribeToProp); + } + + componentWillUnmount() { + this.state.subscriptions.forEach(subscription => { + subscription.unsubscribe(); + }); + } + + componentDidUpdate(prevProps) { + Object.keys(prevProps).forEach(prop => { + if(!prevProps[prop] && this.props[prop]){ + this.subscribeToProp(prop); + } + }); + + // TODO: check if prevProps and currProps are different, and unsubscribe from prevProp + } + + render() { + const props = Object.keys(this.props).reduce((accum, curr) => { + if(!isObservable(this.props[curr])){ + accum[curr] = this.props[curr]; + return accum; + } + return accum; + }, {}); + + return <WrappedComponent {...props} {...this.state.observedValues} />; + } + }; + } + +export default observe; \ No newline at end of file