Skip to content

Instantly share code, notes, and snippets.

@amitava82
Created January 7, 2017 03:21
Show Gist options
  • Save amitava82/9b22bca454e09b387834d0cd4054c35f to your computer and use it in GitHub Desktop.
Save amitava82/9b22bca454e09b387834d0cd4054c35f to your computer and use it in GitHub Desktop.
A simple React component decorator for firebase.
import React from 'react';
import fb from './firebase-decorator';
//watch single path
@fb({
path: props => `users/${props.id}/status`,
valueKey: 'userStatus'
})
class Example extends React.Component {
render(){
return (
<div>
{this.props.userStatus}
</div>
)
}
}
//watch multiple path
@fb([
{
path: props => `users/${props.id}/status`,
valueKey: 'userStatus'
},
{
path: props => `something/${props.id}`,
valueKey: 'someData'
}
])
class Example extends React.Component {
render(){
return (
<div>
{this.props.userStatus}
{JSON.strinfigy(this.props.someData)}
</div>
)
}
}
import React from 'react';
import isArray from 'lodash/isArray';
import find from 'lodash/find';
import firebase from './firebase';
export default function decorator(options) {
return function (Component) {
const handlers = [];
class DecoratedComponent extends React.Component{
constructor(...args){
super(...args);
this.state = {
value: null,
values: {}
}
}
componentWillMount(){
this.sub(this.props);
}
componentWillReceiveProps(nextProps) {
if(isArray(options)) {
const hasChanged = find(options, o => {
return o.path(nextProps) !== o.path(this.props);
});
if(hasChanged) {
this.unsub();
this.sub(nextProps);
}
} else {
if(options.path(nextProps) !== options.path(this.props)) {
this.unsub();
this.sub(nextProps);
}
}
}
componentWillUnmount(){
this.unsub();
}
sub(props) {
if(isArray(options)) {
options.forEach(option => {
this.bind(option, props);
});
} else {
const ref = firebase.firebaseDb.ref(options.path(props));
const fn = snapshot => {
const val = snapshot.val();
this.setState({value: val});
};
ref.on('value', fn);
handlers.push({ref, fn});
}
}
bind(option, props) {
const ref = firebase.firebaseDb.ref(option.path(props));
const fn = snapshot => {
const val = snapshot.val();
this.setState({values: {...this.state.values, [option.valueKey]: val}});
};
ref.on('value', fn);
handlers.push({ref, fn});
}
unsub() {
handlers.forEach(i => i.ref.off('value',i.fn));
handlers.length = 0;
}
render(){
let state = {};
if(isArray(options)) {
state = this.state.values;
} else {
state = {
[options.valueKey] : this.state.value
};
}
return <Component {...this.props} {...state} />
}
}
return DecoratedComponent;
}
}
import firebase from 'firebase';
import {FIREBASE_CONFIG} from '../constants';
const firebaseApp = firebase.initializeApp(process.env.NODE_ENV == 'production' ? FIREBASE_CONFIG.prod : FIREBASE_CONFIG.dev);
const firebaseAuth = firebaseApp.auth();
const firebaseDb = firebaseApp.database();
const firebaseStore = firebaseApp.storage();
const fbProvider = new firebase.auth.FacebookAuthProvider();
export default {
firebaseApp,
firebaseAuth,
firebaseDb,
firebaseStore,
providers: {
facebook: fbProvider
},
TIMESTAMP: firebase.database.ServerValue.TIMESTAMP
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment