mirror of
https://github.com/zhigang1992/reactfire.git
synced 2026-04-02 09:31:16 +08:00
165 lines
4.9 KiB
JavaScript
165 lines
4.9 KiB
JavaScript
/*!
|
|
* ReactFire is an open-source JavaScript library that allows you to add a
|
|
* realtime data source to your React apps by providing and easy way to let
|
|
* Firebase populate the state of React components.
|
|
*
|
|
* ReactFire 0.4.0
|
|
* https://github.com/firebase/reactfire/
|
|
* License: MIT
|
|
*/
|
|
|
|
;(function (root, factory) {
|
|
"use strict";
|
|
if (typeof define === "function" && define.amd) {
|
|
// AMD
|
|
define([], function() {
|
|
return (root.ReactFireMixin = factory());
|
|
});
|
|
} else if (typeof exports === "object") {
|
|
// CommonJS
|
|
module.exports = factory();
|
|
} else {
|
|
// Global variables
|
|
root.ReactFireMixin = factory();
|
|
}
|
|
}(this, function() {
|
|
"use strict";
|
|
|
|
var ReactFireMixin = {
|
|
/********************/
|
|
/* MIXIN LIFETIME */
|
|
/********************/
|
|
/* Initializes the Firebase binding refs array */
|
|
componentWillMount: function() {
|
|
this.firebaseRefs = {};
|
|
this.firebaseListeners = {};
|
|
},
|
|
|
|
/* Removes any remaining Firebase bindings */
|
|
componentWillUnmount: function() {
|
|
for (var key in this.firebaseRefs) {
|
|
if (this.firebaseRefs.hasOwnProperty(key)) {
|
|
this.unbind(key);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
/*************/
|
|
/* BINDING */
|
|
/*************/
|
|
/* Creates a binding between Firebase and the inputted bind variable as an array */
|
|
bindAsArray: function(firebaseRef, bindVar, cancelCallback) {
|
|
this._bind(firebaseRef, bindVar, cancelCallback, true);
|
|
},
|
|
|
|
/* Creates a binding between Firebase and the inputted bind variable as an object */
|
|
bindAsObject: function(firebaseRef, bindVar, cancelCallback) {
|
|
this._bind(firebaseRef, bindVar, cancelCallback, false);
|
|
},
|
|
|
|
/* Creates a binding between Firebase and the inputted bind variable as either an array or object */
|
|
_bind: function(firebaseRef, bindVar, cancelCallback, bindAsArray) {
|
|
this._validateBindVar(bindVar);
|
|
|
|
var errorMessage, errorCode;
|
|
if (Object.prototype.toString.call(firebaseRef) !== "[object Object]") {
|
|
errorMessage = "firebaseRef must be an instance of Firebase";
|
|
errorCode = "INVALID_FIREBASE_REF";
|
|
}
|
|
else if (typeof bindAsArray !== "boolean") {
|
|
errorMessage = "bindAsArray must be a boolean. Got: " + bindAsArray;
|
|
errorCode = "INVALID_BIND_AS_ARRAY";
|
|
}
|
|
|
|
if (typeof errorMessage !== "undefined") {
|
|
var error = new Error("ReactFire: " + errorMessage);
|
|
error.code = errorCode;
|
|
throw error;
|
|
}
|
|
|
|
this.firebaseRefs[bindVar] = firebaseRef.ref();
|
|
this.firebaseListeners[bindVar] = firebaseRef.on("value", function(dataSnapshot) {
|
|
var newState = {};
|
|
if (bindAsArray) {
|
|
newState[bindVar] = this._toArray(dataSnapshot.val());
|
|
}
|
|
else {
|
|
newState[bindVar] = dataSnapshot.val();
|
|
}
|
|
this.setState(newState);
|
|
}.bind(this), cancelCallback);
|
|
},
|
|
|
|
/* Removes the binding between Firebase and the inputted bind variable */
|
|
unbind: function(bindVar) {
|
|
this._validateBindVar(bindVar);
|
|
|
|
if (typeof this.firebaseRefs[bindVar] === "undefined") {
|
|
var error = new Error("ReactFire: unexpected value for bindVar. \"" + bindVar + "\" was either never bound or has already been unbound");
|
|
error.code = "UNBOUND_BIND_VARIABLE";
|
|
throw error;
|
|
}
|
|
|
|
this.firebaseRefs[bindVar].off("value", this.firebaseListeners[bindVar]);
|
|
delete this.firebaseRefs[bindVar];
|
|
delete this.firebaseListeners[bindVar];
|
|
},
|
|
|
|
|
|
/*************/
|
|
/* HELPERS */
|
|
/*************/
|
|
/* Validates the name of the variable which is being bound */
|
|
_validateBindVar: function(bindVar) {
|
|
var errorMessage;
|
|
|
|
if (typeof bindVar !== "string") {
|
|
errorMessage = "bindVar must be a string. Got: " + bindVar;
|
|
}
|
|
else if (bindVar.length === 0) {
|
|
errorMessage = "bindVar must be a non-empty string. Got: \"\"";
|
|
}
|
|
else if (bindVar.length > 768) {
|
|
// Firebase can only stored child paths up to 768 characters
|
|
errorMessage = "bindVar is too long to be stored in Firebase. Got: " + bindVar;
|
|
}
|
|
else if (/[\[\].#$\/\u0000-\u001F\u007F]/.test(bindVar)) {
|
|
// Firebase does not allow node keys to contain the following characters
|
|
errorMessage = "bindVar cannot contain any of the following characters: . # $ ] [ /. Got: " + bindVar;
|
|
}
|
|
|
|
if (typeof errorMessage !== "undefined") {
|
|
var error = new Error("ReactFire: " + errorMessage);
|
|
error.code = "INVALID_BIND_VARIABLE";
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
|
|
/* Returns true if the inputted object is a JavaScript array */
|
|
_isArray: function(obj) {
|
|
return (Object.prototype.toString.call(obj) === "[object Array]");
|
|
},
|
|
|
|
/* Converts a Firebase object to a JavaScript array */
|
|
_toArray: function(obj) {
|
|
var out = [];
|
|
if (obj) {
|
|
if (this._isArray(obj)) {
|
|
out = obj;
|
|
}
|
|
else if (typeof(obj) === "object") {
|
|
for (var key in obj) {
|
|
if (obj.hasOwnProperty(key)) {
|
|
out.push(obj[key]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
};
|
|
|
|
return ReactFireMixin;
|
|
})); |