Skip to content

Instantly share code, notes, and snippets.

@mjackson
Last active February 5, 2016 11:34
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjackson/5b5d87c24907fa4a32ea to your computer and use it in GitHub Desktop.
Save mjackson/5b5d87c24907fa4a32ea to your computer and use it in GitHub Desktop.
A simple mixin for React components that need to bind state to a Firebase ref
var Firebase = require('firebase');
var baseRef = new Firebase('https://my-firebase.firebaseio.com');
function getSnapshotValue(snapshot) {
return snapshot.val();
}
/**
* A mixin for components that want to bind the value of a state variable
* to the value at a Firebase ref.
*/
var FirebaseStateMixin = {
componentWillMount: function () {
this.firebaseRefs = {};
},
componentWillUnmount: function () {
for (var name in this.firebaseRefs)
this.unbindState(name);
},
/**
* Destroys the one-way binding between Firebase and the state variable
* with the given name, if one exists.
*/
unbindState: function (name) {
if (!this.firebaseRefs[name])
return;
this.firebaseRefs[name].off('value');
delete this.firebaseRefs[name];
},
/**
* Sets up a one-way binding from the given ref to the state variable with
* the given name. The createValueFromSnapshot function is used to coerce
* a snapshot to the value of the variable. If not given, it defaults to
* using snapshot.val(). Returns the ref.
*
* Note: Binding to the same value twice overwrites the previous binding.
*/
bindState: function (name, ref, createValueFromSnapshot) {
createValueFromSnapshot = createValueFromSnapshot || getSnapshotValue;
if (this.firebaseRefs[name])
this.unbindState(name); // Automatically unbind.
if (typeof ref === 'string')
ref = baseRef.child(ref);
ref.on('value', function (snapshot) {
if (!this.isMounted())
return;
var newState = {};
newState[name] = createValueFromSnapshot(snapshot);
if (this.componentWillReceiveBoundState)
this.componentWillReceiveBoundState(newState);
this.setState(newState);
}, this);
return ref;
},
/**
* Uses this.bindState() to setup a one-way binding between the given ref
* and the state variable with the given name. The value of the variable will
* be an array created from the children of the snapshot in order of precedence.
* The createValueFromSnapshot function is used to create values in the array.
* If not given, it defaults to using snapshot.val(). Returns the ref.
*/
bindStateAsArray: function (name, ref, createValueFromSnapshot) {
createValueFromSnapshot = createValueFromSnapshot || getSnapshotValue;
return this.bindState(name, ref, function (snapshot) {
var values = [];
snapshot.forEach(function (s) {
values.push(createValueFromSnapshot(s));
});
return values;
});
},
/**
* Uses this.bindState() to setup a one-way binding between the given ref
* and the state variable with the given name. The value of the variable will
* be the number of children of the snapshot (i.e. snapshot.numChildren()).
*/
bindStateAsCount: function (name, ref) {
return this.bindState(name, ref, function (snapshot) {
return snapshot.numChildren();
});
}
};
module.exports = FirebaseStateMixin;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment