From 353d40aa2c3d6558ebf88650560ee4bd715dfafa Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Wed, 28 Aug 2019 09:11:48 -0400 Subject: [PATCH] observe HOC (#15) * observe HOC * feat: subscribe to new observables * pass only non observable props to wrapped component --- test/observables/src/App.js | 65 ++++++++++------------ test/observables/src/EscrowObservator.js | 19 +++++++ test/observables/src/observe.js | 71 ++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 37 deletions(-) create mode 100644 test/observables/src/EscrowObservator.js create mode 100644 test/observables/src/observe.js 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 ; - //return -}; - -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
- - {this.state.escrow && } -
; + return ( +
+ + +
+ ); } } 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

Loading...

; + return ( + + ); +}; + +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 ; + } + }; + } + +export default observe; \ No newline at end of file