Skip to content

Instantly share code, notes, and snippets.

@amccloud
Last active May 9, 2016 02:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save amccloud/d60aa92797b932f72649 to your computer and use it in GitHub Desktop.
Save amccloud/d60aa92797b932f72649 to your computer and use it in GitHub Desktop.
import {Component} from 'React';
export default function observe(Wrapped, observe) {
observe = observe || Wrapped.observe;
if (!observe) {
throw new Error('Components using observe must define observables.');
}
return class ObserveWrapper extends Component {
constructor(props, context) {
super(props, context);
this._subscriptions = {};
}
componentWillMount() {
this._subscribe(this.props, this.context);
}
componentWillReceiveProps(nextProps, nextContext) {
if (nextProps !== this.props || nextContext !== this.context) {
this._subscribe(nextProps, nextContext);
}
}
componentWillUnmount() {
this._unsubscribe();
}
render() {
return <Wrapped {...this.props} {...this.state} />;
}
_subscribe(props, context) {
let subscriptions = {};
let observables = observe(props, context);
for (let key in observables) {
let observable = observables[key];
if (!observable.subscribe) {
__DEV__ && console.warn(`Observable '${key}' is not subscribable.`);
continue;
}
subscriptions[key] = observable.subscribe({
onNext: this._handleNext.bind(this, key),
onError: this._handleError.bind(this, key),
onCompleted: this._handleCompleted.bind(this, key)
});
}
this._unsubscribe();
this._subscriptions = subscriptions;
}
_unsubscribe() {
for (let key in this._subscriptions) {
let subscription = this._subscriptions[key];
if (!subscription.dispose) {
__DEV__ && console.warn(`Observable '${key}' subscription is not disposable.`);
continue;
}
subscription.dispose();
}
this._subscriptions = {};
}
_handleNext(key, value) {
let data = {};
data[key] = value;
this.setState(data);
}
_handleError(key, value) {
throw value;
}
_handleCompleted(key, value) {
}
}
}
import {
Component,
StyleSheet,
ListView,
Image,
TouchableHighlight,
Text
} from 'react-native';
import Dimensions from 'Dimensions';
import {Parse} from 'parse';
import {ParseReact} from 'parse-react';
import observe from '../observe';
class DiscoverController extends Component {
static observe(props, context) {
return {
photos: new Parse.Query('Photo').descending('createdAt')
};
}
state = {
dataSource: new ListView.DataSource({
rowHasChanged: (oldRow, newRow) => {
return oldRow !== newRow;
}
})
}
componentWillReceiveProps(nextProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(nextProps.photos)
});
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)} />
);
}
renderRow(photo) {
return (
<TouchableHighlight>
<Image
style={styles.image}
source={{uri: photo.uri}} />
</TouchableHighlight>
);
}
}
var styles = StyleSheet.create({
image: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').width
}
});
export default observe(DiscoverController);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment