Skip to content

Commit 4587977

Browse files
committed
Create a HoC as an alternative to the mixin
1 parent e7fddf4 commit 4587977

File tree

4 files changed

+97
-3
lines changed

4 files changed

+97
-3
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@
2525
"babel-eslint": "^4.1.7",
2626
"eslint": "^0.22.1",
2727
"mocha": "^2.2.5"
28+
},
29+
"peerDependencies": {
30+
"react": "^0.14.0 || ^15.0.0"
2831
}
2932
}

src/HoC.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import React from 'react';
2+
import {ensure} from './util';
3+
import {update, unmount} from './Mixin';
4+
5+
// Mixin for RethinkDB query subscription support in React components. You'll
6+
// generally want to use DefaultHoC or PropsHoC, which use BaseHoC to
7+
// create more usable versions.
8+
//
9+
// In your component, you should define an observe(props, state) function that
10+
// returns an object mapping query names to QueryRequests. See
11+
// QueryRequest.js for the API.
12+
//
13+
// In the child component, you will have access to this.props.data, which is an
14+
// object mapping from the same query names returned in observe() to the
15+
// results of each query as an QueryResult. See QueryResult.js for the
16+
// API.
17+
//
18+
// Here is a simple example of the mixin API:
19+
// const observe = (props, state) => ({
20+
// turtles: new QueryRequest({
21+
// query: r.table('turtles'),
22+
// changes: true,
23+
// initial: [],
24+
// }),
25+
// });
26+
27+
// class App extends Component {
28+
// render() {
29+
// return <div>
30+
// {this.props.data.turtles.value().map(function(x) {
31+
// return <div key={x.id}>{x.firstName}</div>;
32+
// })};
33+
// </div>;
34+
// },
35+
// };
36+
37+
// BaseHoC(new Session())(observe)(App);
38+
39+
export const BaseHoC = sessionGetter => observe => ChildComponent => class ReactRethinkDB extends React.Component {
40+
constructor(props, state) {
41+
super();
42+
this.observe = observe;
43+
}
44+
45+
componentWillMount() {
46+
const session = sessionGetter(this);
47+
this.dispatch = session.runQuery.bind(session);
48+
ensure(session && session._subscriptionManager,
49+
`Must define Session`);
50+
ensure(this.observe, `Must define observe()`);
51+
ensure(session._connPromise, `Must connect() before mounting react-rethinkdb`);
52+
this._rethinkMixinState = {session, subscriptions: {}};
53+
this.data = this.data || {};
54+
update(this, this.props, this.state);
55+
}
56+
57+
componentDidMount() {
58+
this._rethinkMixinState.isMounted = true;
59+
}
60+
61+
componentWillUnmount() {
62+
unmount(this);
63+
this._rethinkMixinState.isMounted = false;
64+
}
65+
66+
componentWillUpdate(nextProps, nextState) {
67+
if (nextProps !== this.props || nextState !== this.state) {
68+
update(this, nextProps, nextState);
69+
}
70+
}
71+
72+
render() {
73+
return <ChildComponent data={this.data} dispatch={this.dispatch} {...this.props} />;
74+
}
75+
};
76+
77+
// HoC that uses rethink session from props. For example:
78+
// class MyComponent extends Component {
79+
// ...
80+
// });
81+
// var session = new Session();
82+
// React.render(<MyComponent rethinkSession={session} />, mountNode);
83+
export const PropsHoC = name => BaseHoC(component => component.props[name]);

src/Mixin.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {QueryResult} from './QueryResult';
22
import {ensure} from './util';
33

4-
const update = (component, props, state) => {
4+
export const update = (component, props, state) => {
55
const observed = component.observe(props, state);
66
const {session, subscriptions} = component._rethinkMixinState;
77
const subscriptionManager = session._subscriptionManager;
@@ -27,7 +27,7 @@ const update = (component, props, state) => {
2727
});
2828
};
2929

30-
const unmount = component => {
30+
export const unmount = component => {
3131
const {subscriptions} = component._rethinkMixinState;
3232
Object.keys(subscriptions).forEach(key => {
3333
subscriptions[key].unsubscribe();

src/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {BaseHoC, PropsHoC} from './HoC';
12
import {BaseMixin, PropsMixin} from './Mixin';
23
import {QueryRequest} from './QueryRequest';
34
import {MetaSession} from './Session';
@@ -12,24 +13,31 @@ const DefaultSession = new Session();
1213
// Singleton mixin for convenience, which uses the DefaultSession singleton as
1314
// the session.
1415
const DefaultMixin = BaseMixin(() => DefaultSession);
16+
const DefaultHoC = BaseHoC(() => DefaultSession);
1517

1618
const ReactRethinkdb = {
1719
BaseMixin,
1820
PropsMixin,
21+
BaseHoC,
22+
PropsHoC,
1923
QueryRequest,
2024
r,
2125
Session,
2226
DefaultSession,
23-
DefaultMixin
27+
DefaultMixin,
28+
DefaultHoC
2429
};
2530

2631
export {
2732
BaseMixin,
2833
PropsMixin,
34+
BaseHoC,
35+
PropsHoC,
2936
QueryRequest,
3037
r,
3138
Session,
3239
DefaultSession,
3340
DefaultMixin,
41+
DefaultHoC,
3442
ReactRethinkdb as default,
3543
};

0 commit comments

Comments
 (0)