observe HOC (#15)

* observe HOC
* feat: subscribe to new observables
* pass only non observable props to wrapped component
This commit is contained in:
Richard Ramos 2019-08-28 09:11:48 -04:00 committed by GitHub
parent ff102b34b2
commit 353d40aa2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 118 additions and 37 deletions

View File

@ -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>
);
}
}

View File

@ -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;

View File

@ -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;