Skip to content

Commit

Permalink
Create a HoC as an alternative to the mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
chrbala committed Sep 7, 2016
1 parent e7fddf4 commit 4587977
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 3 deletions.
3 changes: 3 additions & 0 deletions package.json
Expand Up @@ -25,5 +25,8 @@
"babel-eslint": "^4.1.7",
"eslint": "^0.22.1",
"mocha": "^2.2.5"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0"
}
}
83 changes: 83 additions & 0 deletions src/HoC.js
@@ -0,0 +1,83 @@
import React from 'react';
import {ensure} from './util';
import {update, unmount} from './Mixin';

// Mixin for RethinkDB query subscription support in React components. You'll
// generally want to use DefaultHoC or PropsHoC, which use BaseHoC to
// create more usable versions.
//
// In your component, you should define an observe(props, state) function that
// returns an object mapping query names to QueryRequests. See
// QueryRequest.js for the API.
//
// In the child component, you will have access to this.props.data, which is an
// object mapping from the same query names returned in observe() to the
// results of each query as an QueryResult. See QueryResult.js for the
// API.
//
// Here is a simple example of the mixin API:
// const observe = (props, state) => ({
// turtles: new QueryRequest({
// query: r.table('turtles'),
// changes: true,
// initial: [],
// }),
// });

// class App extends Component {
// render() {
// return <div>
// {this.props.data.turtles.value().map(function(x) {
// return <div key={x.id}>{x.firstName}</div>;
// })};
// </div>;
// },
// };

// BaseHoC(new Session())(observe)(App);

export const BaseHoC = sessionGetter => observe => ChildComponent => class ReactRethinkDB extends React.Component {
constructor(props, state) {
super();
this.observe = observe;
}

componentWillMount() {
const session = sessionGetter(this);
this.dispatch = session.runQuery.bind(session);
ensure(session && session._subscriptionManager,
`Must define Session`);
ensure(this.observe, `Must define observe()`);
ensure(session._connPromise, `Must connect() before mounting react-rethinkdb`);
this._rethinkMixinState = {session, subscriptions: {}};
this.data = this.data || {};
update(this, this.props, this.state);
}

componentDidMount() {
this._rethinkMixinState.isMounted = true;
}

componentWillUnmount() {
unmount(this);
this._rethinkMixinState.isMounted = false;
}

componentWillUpdate(nextProps, nextState) {
if (nextProps !== this.props || nextState !== this.state) {
update(this, nextProps, nextState);
}
}

render() {
return <ChildComponent data={this.data} dispatch={this.dispatch} {...this.props} />;
}
};

// HoC that uses rethink session from props. For example:
// class MyComponent extends Component {
// ...
// });
// var session = new Session();
// React.render(<MyComponent rethinkSession={session} />, mountNode);
export const PropsHoC = name => BaseHoC(component => component.props[name]);
4 changes: 2 additions & 2 deletions src/Mixin.js
@@ -1,7 +1,7 @@
import {QueryResult} from './QueryResult';
import {ensure} from './util';

const update = (component, props, state) => {
export const update = (component, props, state) => {
const observed = component.observe(props, state);
const {session, subscriptions} = component._rethinkMixinState;
const subscriptionManager = session._subscriptionManager;
Expand All @@ -27,7 +27,7 @@ const update = (component, props, state) => {
});
};

const unmount = component => {
export const unmount = component => {
const {subscriptions} = component._rethinkMixinState;
Object.keys(subscriptions).forEach(key => {
subscriptions[key].unsubscribe();
Expand Down
10 changes: 9 additions & 1 deletion src/index.js
@@ -1,3 +1,4 @@
import {BaseHoC, PropsHoC} from './HoC';
import {BaseMixin, PropsMixin} from './Mixin';
import {QueryRequest} from './QueryRequest';
import {MetaSession} from './Session';
Expand All @@ -12,24 +13,31 @@ const DefaultSession = new Session();
// Singleton mixin for convenience, which uses the DefaultSession singleton as
// the session.
const DefaultMixin = BaseMixin(() => DefaultSession);
const DefaultHoC = BaseHoC(() => DefaultSession);

const ReactRethinkdb = {
BaseMixin,
PropsMixin,
BaseHoC,
PropsHoC,
QueryRequest,
r,
Session,
DefaultSession,
DefaultMixin
DefaultMixin,
DefaultHoC
};

export {
BaseMixin,
PropsMixin,
BaseHoC,
PropsHoC,
QueryRequest,
r,
Session,
DefaultSession,
DefaultMixin,
DefaultHoC,
ReactRethinkdb as default,
};

0 comments on commit 4587977

Please sign in to comment.