Skip to content

Instantly share code, notes, and snippets.

@peerreynders
Created April 21, 2018 18:35
Show Gist options
  • Save peerreynders/ff56e1243f0efa58dbe411be002d96ac to your computer and use it in GitHub Desktop.
Save peerreynders/ff56e1243f0efa58dbe411be002d96ac to your computer and use it in GitHub Desktop.
RxJS in Action Ch10 2A: Communicating to child components using a single parent
// file: src/index.js - Derived from:
// RxJS in Action (2017, Manning), 978-1-617-29341-2
// by Paul P. Daniels and Luis Atencio
// Listing:
// 10.2 Communicating to child components using a single parent (p.280)
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import Rx from 'rxjs';
// --- Listing 10.2 Communicating to child components using a single parent
// Presentation Components
const locale = 'en-US';
const currency = 'USD';
const balanceFormat =
new Intl.NumberFormat(locale, {style: 'currency', currency});
const AccountBalance = ({name, amount}) =>
<div>{name}: {balanceFormat.format(amount)}</div>;
AccountBalance.propTypes = {
name : PropTypes.string,
amount : PropTypes.number
};
const BalancesView =({checking, savings}) =>
<div>
<AccountBalance {...{name: 'Checking', amount: checking}}/>
<AccountBalance {...{name: 'Savings', amount: savings}}/>
</div>;
BalancesView.propTypes = {
checking : PropTypes.number,
savings : PropTypes.number
};
// Container Component
const initialState = () => ({
checking: 0,
savings: 0
});
const balanceToState = ([checking, savings]) =>
({checking, savings});
class Balances extends Component {
constructor(props){
super(props);
this.state = initialState();
this.unsubscribe = null;
}
send = (state) => {
this.setState((_prevState, _props) => state);
}
componentDidMount() {
const {send, props: {balance$}} = this;
const subscription =
balance$
.map(balanceToState)
.subscribe(send);
this.unsubscribe = () => subscription.unsubscribe();
}
componentWillUnmount() {
const {unsubscribe} = this;
if(unsubscribe) {
unsubscribe();
this.unsubscribe = null;
}
}
render() {
const {props: {render}, state: accounts} = this;
return render(accounts);
}
}
Balances.propTypes = {
balance$ : PropTypes.object.isRequired,
render : PropTypes.func.isRequired
};
const checking$ = Rx.Observable.timer(0, 1000);
const savings$ = Rx.Observable.timer(0, 1000 * 5);
const balance$ = Rx.Observable.combineLatest(checking$,savings$)
ReactDOM.render(
<Balances {...{balance$, render: BalancesView}}/>,
document.getElementById('root')
);
// --- Listing 10.2 end
registerServiceWorker();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment