Immutables, ReactJS, and RxJS

node v0.12.18
version: 1.0.0
endpointsharetweet
First, let's go ahead and import all this nonesnse!
const Rx = require('rx'); const Immutable = require('immutable'); const uuid = require('node-uuid'); const React = require('react'); 'loaded requirements';
Now let's define an Immutable.Record
const Customer = Immutable.Record({ name: 'Anonymous', favoriteColor: undefined }); 'created immutable record';
(Some fake data)
let fakeCustomers = [ new Customer({ name: 'Luke Skywalker', favoriteColor: 'green' }), new Customer({ name: 'Anakin Skywalker', favoriteColor: 'blue' }), new Customer({ name: 'Mace Windu', favoriteColor: 'purple' }) ] 'made some fake customers';
Here we'll define a react component.
var CustomerProfileV1 = React.createClass({ componentWillMount: function() { // Here we'd ask for a customer, if we had one... }, getInitialState: function() { return { loading: true } }, render: function() { const customerInfo = (<div> <p>{this.props.customer.name}</p> <p>{this.props.customer.favoriteColor}</p> </div>); const loading = ( <p>Loading...</p> ); return (<div> <p>{this.props.customer.name}</p> </div>); } }); 'create a basic component';
So, we have a component that doesn't have access to the data model. We could now turn to flux patterns, storage patterns, cry ourselves to sleep because of data consistency blah blah blah. Or, we could use Observables, and not need yet another framework.
function _fakeQuery(params) { return new Promise(resolve => { resolve(fakeCustomers.filter(val => { for (key in params) { if (val[key] !== params[key]) { return false; } } return true; })); }); } function CustomerService() { this.customers = new Rx.BehaviorSubject(null); } CustomerService.prototype = { fetchCustomer: function(params) { _fakeQuery(params) .then(customers => this.customers.onNext(customers.shift())); return this.makeSubscription(params); }, fetchCustomers: function(params) { _fakeQuery(params) .then(customers => { for (let i = 0; i < customers.length;i++) { this.customers.onNext(customers[i]) } }); return this.makeSubscription(params); }, fakeFetch: function(fakeCustomer) { this.customers.onNext(fakeCustomer); }, makeSubscription: function(params) { return this.customers.filter(val => { if (!val) { return false; } for (key in params) { if (val[key] !== params[key]) { return false; } } return true; }); } } global.customerService = new CustomerService(); 'create the basic customer service';
await new Promise(resolve => { customerService.fetchCustomer({favoriteColor: 'green'}).subscribe(customer => { resolve(customer); }); });
Now say the customer is modified somewhere else, by another component or by a service,
let resultCount = 0; let subscription = customerService.makeSubscription({favoriteColor: 'green'}).subscribe(customer => { resultCount++; console.log(`[${resultCount}] record: ${customer}`); // Just here so we don't clutter the logs later if (resultCount === 2) { subscription.dispose(); } }); fakeCustomers[0] = new Customer({ name: 'Yoda', favoriteColor: 'green' }); customerService.fetchCustomer({favoriteColor: 'green'}); 'changing the customer';
Great, now we have a way to track the changes to one customer, but what if we have a component that wants updates from MULTIPLE customers, maybe even all customers for the time being.
var CustomersView = React.createClass({ componentWillMount: function() { const self = this; customerService.makeSubscription({}).subscribe(customers => { self.loading = false; for (let i = 0; i < customers.length; i++) { let customer = customers[i]; this.state.customers[customer.name] = customer; } }); }, getInitialState: function() { return { loading: true, customers: {} } }, render: function() { const customers = (<div> { Object.keys(this.state.customers).map(key => { return <CustomerProfile customer={this.state.customers[key]}></CustomerProfile> }) } </div>); const loading = ( <p>Loading...</p> ); return (<div> <p>{this.state.customer.name}</p> </div>); } }); 'Built CustomersView';
customerService.makeSubscription().subscribe(customer => { console.log(`record: ${customer}`); }); customerService.fetchCustomers({}); 'Subscribe to all updates';
Loading…

no comments

    sign in to comment