Nativescript Firebase plugin - "cannot read property of null" after upgrade to NS 3.4.0


#1

My angular - Nativescript project uses the Nativescript-Firebase-Plugin. It works perfectly well in Nativescript 3.3

I upgraded my project to Nativescript 3.4. After upgrading the project, I am facing a major issue with all firebase queries.

**JS: Error in firebase.query: TypeError: Cannot read property 'child' of null**
JS: NO QUESTIONS FOR THIS USER
JS: ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined
JS: TypeError: Cannot read property 'length' of undefined
JS:     at file:///data/data/org.nativescript.qbank/files/app/feed/alphaCreate.component.js:55:23
JS:     at SafeSubscriber.schedulerFn [as _next] (file:///data/data/org.nativescript.qbank/files/app/tns_modules/@angular/core/bundles/core.umd.js:3870:36)
JS:     at SafeSubscriber.__tryOrUnsub (file:///data/data/org.nativescript.qbank/files/app/tns_modules/rxjs/Subscriber.js:238:16)
JS:     at SafeSubscriber.next (file:///data/data/org.nativescript.qbank/files/app/tns_modules/rxjs/Subscriber.js:185:22)
JS:     at Subscriber._next (file:///data/data/org.nativescript.qbank/files/app/tns_modules/rxjs/Subscriber.js:125:26)
JS:     at Subscriber.next (file:///data/data/org.nativescript.qbank/files/app/tns_modules/rxjs/Subscriber.js:89:18)
JS:     at EventEmitter.Subject.next (file:///data/data/org.nativescript.qbank/files/app/tns_modules/rxjs/Subject.js:55:25)
JS:     at EventEmitter.emit (file:///data/data/org.nativescript.qbank/files/app/tns_modules/@angular/core/bundles/core.umd.js:3844:76)
JS:     at file:///data/data/org.nativescript.qbank/files/app/services/my-questions.service.js:51:42
JS:     at ZoneDelegate.invoke (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:365:26)
JS:     at Object.onInvoke (file:///data/data/org.nativescript.qbank/files/app/tns_modules/@angular/core/bundles/core.umd.js:4156:37)
JS:     at ZoneDelegate.invoke (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:364:32)
JS:     at Zone.run (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:125:43)
JS:     at file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:760:57
JS:     at ZoneDelegate.invokeTask (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:398:31)

I tried to resolve it by
a. upgrading the native script firebase plugin: 5.0.5
b. upgrading all the dependenices of the project

But the issue is still occurring. This is a big blocker, and Please suggest what I can do to fix this.

My package json is as below:

{
  "android": {
    "markingMode": "none"
  },
  "description": "NativeScript Application",
  "license": "SEE LICENSE IN <your-license-filename>",
  "readme": "NativeScript Application",
  "repository": "<fill-your-repository-here>",
  "nativescript": {
    "id": "org.nativescript.qbank",
    "tns-ios": {
      "version": "3.4.0"
    },
    "tns-android": {
      "version": "3.4.0"
    }
  },
  "dependencies": {
    "@angular/animations": "~5.0.0",
    "@angular/common": "~5.0.0",
    "@angular/compiler": "~5.0.0",
    "@angular/core": "~5.0.0",
    "@angular/forms": "~5.0.0",
    "@angular/http": "~5.0.0",
    "@angular/platform-browser": "~5.0.0",
    "@angular/platform-browser-dynamic": "~5.0.0",
    "@angular/router": "~5.0.0",
    "nativescript-algolia": "0.0.4",
    "nativescript-angular": "~5.0.0",
    "nativescript-camera": "^3.1.4",
    "nativescript-email": "^1.5.1",
    "nativescript-fancyalert": "^1.1.2",
    "nativescript-filter-select": "^1.2.1",
    "nativescript-geolocation": "^3.0.0",
    "nativescript-gif": "^1.0.9",
    "nativescript-imagepicker": "^4.0.1",
    "nativescript-iqkeyboardmanager": "^1.1.0",
    "nativescript-loading-indicator": "^2.3.2",
    "nativescript-plugin-firebase": "^5.0.5",
    "nativescript-pro-ui": "^3.3.0",
    "nativescript-theme-core": "~1.0.4",
    "nativescript-toast": "^1.4.5",
    "nativescript-web-image-cache": "^4.2.2",
    "reflect-metadata": "~0.1.8",
    "rxjs": "^5.5.0",
    "tns-core-modules": "^3.4.0"
  },
  "devDependencies": {
    "babel-traverse": "6.26.0",
    "babel-types": "6.26.0",
    "babylon": "6.18.0",
    "codelyzer": "~4.0.2",
    "es6-promise-loader": "^1.0.2",
    "lazy": "1.0.11",
    "nativescript-dev-typescript": "^0.6.0",
    "tslint": "^5.1.0",
    "typescript": "~2.4.2",
    "zone.js": "^0.8.4"
  }
}


#2

We need to see the block of code around:

file:///data/data/org.nativescript.qbank/files/app/feed/alphaCreate.component.js:55:1234

In order to actually provide any guidance.


#3

Hi @sean-perkins,

Thanks for your response. I have pasted the code for the component below.

The component is below and I have highlighted the specific place where the issue seems to be occuring onloaded in the “myQuestionsSubscription” where the results need to be returned from firebase. Iam also including the specific function from the service that executes the firebase query.

This is also happening for all firebase database queries (not just this one!)

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var router_1 = require("@angular/router");
var nativescript_web_image_cache_1 = require("nativescript-web-image-cache"); // to cache images
var observable_array_1 = require("data/observable-array"); //This import is to make the question list as observable array.
var page_1 = require("ui/page");
var platform_1 = require("platform"); // required to push elments into view in android
// import { LoadingIndicator } from "nativescript-loading-indicator";
var loading_service_1 = require("../services/loading.service"); // to save selected image
var userStatus_service_1 = require("../services/userStatus.service");
var my_questions_service_1 = require("../services/my-questions.service");
// import { ModalDialogService } from "nativescript-angular/directives/dialogs"; // For email print modal view
var application_settings_1 = require("application-settings");
var AlphaCreateComponent = /** @class */ (function () {
   function AlphaCreateComponent(router, page, userStatusService, myQuestionsService, loadingService, _changeDetectionRef, zone) {
       this.router = router;
       this.page = page;
       this.userStatusService = userStatusService;
       this.myQuestionsService = myQuestionsService;
       this.loadingService = loadingService;
       this._changeDetectionRef = _changeDetectionRef;
       this.zone = zone;
       this.monthArray = [
           'JANUARY', 'FEBRUARY', 'MARCH', 'APRIL', 'MAY', 'JUNE', 'JULY', 'AUGUST', 'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER'
       ];
       this.templateSelectorFunction = function (item, index, items) {
           if (item) {
               console.log("Item.type is" + item.questionType);
               return item.questionType;
           }
       };
       nativescript_web_image_cache_1.initializeOnAngular();
       this.isTablet = application_settings_1.getBoolean('isTablet');
       page.actionBarHidden = true;
       this.colors = ['#ff78a4', '#bdabff', '#41dbda', '#ffbe4c', '#3ec6ff', '#ff6868'];
       this.monthImages = ['res://jan', 'res://feb', 'res://mar', 'res://apr', 'res://may', 'res://jun',
           'res://jul', 'res://aug', 'res://sep', 'res://oct', 'res://nov', 'res://dec'];
       this.questionListAvailable = true;
       this.numberOfQuestionsCreated = "0";
   }
   AlphaCreateComponent.prototype.ngOnInit = function () {
       // this.loader.show(this.options);
       // get user ID
       this.uid = JSON.parse(this.userStatusService.getUser()).uid;
       this.myQuestionsArray = [];
       this.myQuestionsList = new observable_array_1.ObservableArray();
       this.arrayToView = new observable_array_1.ObservableArray();
       this._templateSelector = this.templateSelectorFunction;
   };
   AlphaCreateComponent.prototype.onloaded = function () {
       this.loadingService.showProcessingLoader();
       var self = this;
       this.myQuestionsSubscription = this.myQuestionsService.myQuestionsEventEmitter.subscribe(function (result) {
           if (result.length && result.length >= 1) {
               self.questionListAvailable = true;
               // self.decideWhichViewToShow(result);
               // self.myQuestionsArray = result;
               self.flattenObjectKeys(result);
               self.numberOfQuestionsCreated = self.myQuestionsArray.length.toString();
               self.sortQuestionListByDate(self.myQuestionsArray);
               // this.processDataForView();
               // console.log("this is the result in mytest component" + JSON.stringify(result));
               // self.myQuestionsList = new ObservableArray(result);
           }
           else {
               self.questionListAvailable = false;
               self.loadingService.hideProcessingLoader();
           }
       });
       this.myQuestionsService.getUserQuestionList();
   };
   Object.defineProperty(AlphaCreateComponent.prototype, "templateSelector", {
       // get set and templateSeclector function for radlistview templates
       get: function () {
           return this._templateSelector;
       },
       set: function (value) {
           this._templateSelector = value;
       },
       enumerable: true,
       configurable: true
   });
   AlphaCreateComponent.prototype.flattenObjectKeys = function (list) {
       var self = this;
       var questionList = list;
       var newQuestionObject = {};
       questionList.forEach(function (element) {
           // tslint:disable-next-line:forin
           for (var key in element) {
               if (key) {
                   newQuestionObject = element[key];
                   var qTypeLowercase = element[key].questionType.toLowerCase();
                   newQuestionObject['questionType'] = qTypeLowercase;
                   newQuestionObject['objectId'] = key;
               }
               var isoDateString = element[key].dateCreated;
               var dateObject = new Date(isoDateString);
               newQuestionObject['formattedDate'] = dateObject;
               self.myQuestionsArray.push(newQuestionObject);
           }
       });
       console.log("myQuestionsArray done");
   };
   AlphaCreateComponent.prototype.sortQuestionListByDate = function (result) {
       var self = this;
       var questionList = result;
       // To sort questions by date created
       questionList.sort(function (orderA, orderB) {
           var createdAtA = orderA.formattedDate;
           var createdAtB = orderB.formattedDate;
           return (createdAtA > createdAtB) ? -1 : (createdAtA < createdAtB) ? 1 : 0;
       });
       console.log("the sorted questionListData looks like this" + questionList);
       setTimeout(function () {
           self.myQuestionsList.push(questionList);
           self.processDataForView();
       }, 100);
   };
   AlphaCreateComponent.prototype.createQuestion = function () {
       console.log("Am in create Question ");
       var comingToCreateFrom = "New Q";
       var navigationParams = {
           queryParams: {
               comingToCreateFrom: comingToCreateFrom,
           },
       };
       console.log("In Alpha, coming to Create From as " + comingToCreateFrom);
       this.router.navigate(['question-type'], navigationParams);
       // console.log("In create question handler");
   };
   AlphaCreateComponent.prototype.onUnloaded = function () {
       //remove any active subscriptions here
       this.myQuestionsSubscription.unsubscribe();
       console.log("Question Subscription Unsubscribed");
   };
   /**
    * changeItToString
    * It returns the updated index to the question.
    * This is for test perpose. We need to re-think if anything comes out in IOS
    */
   AlphaCreateComponent.prototype.changeItToString = function (index) {
       // console.log("Value of index is as follows: " + index);
       return (index).toString();
   };
   AlphaCreateComponent.prototype.questionNumberToAlphabetConverter = function (index) {
       var conversionChart = ['a.', 'b.', 'c.', 'd.', 'e.', 'f.', 'g.', 'h.', 'i.', 'j.'];
       return conversionChart[index];
   };
   AlphaCreateComponent.prototype.processDataForView = function () {
       var _this = this;
       var self = this;
       var currentMonthIndex = null;
       this.myQuestionsList.forEach(function (element, i) {
           //Soumen[08/09/207]: We need the remainder for the color index.
           element.bgColor = _this.colors[(i % self.colors.length)];
           // element.alphabet = element.testName.charAt(0);
           if (element.formattedDate && element.formattedDate.getMonth()) {
               console.log("In processing view data month index is" + element.formattedDate.getMonth());
               if (currentMonthIndex !== element.formattedDate.getMonth()) {
                   // console.log("current month index: " + currentMonthIndex + "elements month: " + element.formattedDate.getMonth());
                   currentMonthIndex = element.formattedDate.getMonth();
                   // console.log("After assignment current month index: " + currentMonthIndex);
                   var temp = {};
                   temp['text'] = self.monthArray[currentMonthIndex] + " " + element.formattedDate.getFullYear().toString();
                   temp['questionType'] = "month";
                   temp['imagePath'] = self.monthImages[currentMonthIndex];
                   // console.log("After assignment into temp, Temp is like: " + JSON.stringify(temp));
                   // console.log("Status of the array to view before pushing into array: " + this.arrayToView.length);
                   self.arrayToView.push(temp);
                   // console.log("Timeline template: " + JSON.stringify(temp));
               }
               // self.arrayToView.push(element);
               if (platform_1.isAndroid) {
                   self.zone.run(function () {
                       self.arrayToView.push(element);
                   });
               }
               else {
                   self.arrayToView.push(element);
               }
           }
           // console.log("Array to View is" + JSON.stringify(self.arrayToView));
       });
       this.loadingService.hideProcessingLoader();
   };
   AlphaCreateComponent = __decorate([
       core_1.Component({
           moduleId: module.id,
           selector: "feed",
           templateUrl: "./alphaCreate.component.html",
       }),
       __metadata("design:paramtypes", [router_1.Router,
           page_1.Page,
           userStatus_service_1.UserStatusService,
           my_questions_service_1.MyQuestionsService,
           loading_service_1.LoadingService,
           core_1.ChangeDetectorRef,
           core_1.NgZone])
   ], AlphaCreateComponent);
   return AlphaCreateComponent;
}());
exports.AlphaCreateComponent = AlphaCreateComponent;

The service is (in typescript):

getUserQuestionList() {
        const userId = JSON.parse(this.userStatusService.getUser()).uid;
        const self = this;
        firebase.query(
            function () { },
            "dev/user/" + userId + "/myQuestions",
            {
                singleEvent: true,
                orderBy: {
                    type: firebase.QueryOrderByType.CHILD,
                    value: 'since',
                },
            },
        ).then(function (result) {
            if (result) {
                const myQuestionsArray = [];
                for (let key in result.value) {
                    if (result.value.hasOwnProperty(key)) {
                        const questionObject = {};
                        questionObject[key] = result.value[key];
                        myQuestionsArray.push(questionObject);
                        console.log("myQUestions array is " + myQuestionsArray);
                    }
                }
                console.log("MY QUESTIONS LIST IS " + myQuestionsArray);
                self.myQuestionsEventEmitter.emit(myQuestionsArray);
            }
        }, function (error) {
            console.log("NO QUESTIONS FOR THIS USER");
            self.myQuestionsEventEmitter.emit(error.value);
        });
    }

#4

I agree something larger is most likely at play.

What is the value you are getting back for result in this expression:

firebase.query(
            function () { },
            "dev/user/" + userId + "/myQuestions",
            {
                singleEvent: true,
                orderBy: {
                    type: firebase.QueryOrderByType.CHILD,
                    value: 'since',
                },
            },
        ).then(function (result) {

Also you are emitting an error value here:

self.myQuestionsEventEmitter.emit(error.value);

which is going to break all your downstream logic when you do have issues like this, because your logic is checking for length and then acting like it received back a valid response.


#5

Hi @sean-perkins,

Thanks for highlighting the issue on length (have fixed that). I executed the code in debug mode and found that the firebase query function is not returning any result - the program just gets stuck there. The following is logged in the console:

JS: Error in firebase.query: TypeError: Cannot read property 'child' of null
JS: Error when checking registration: Cannot read property 'child' of null

Any suggestions, please?


#6

Were you able to successfully run firebase.init(options)?


#7

I noticed you are using 5.0+ which includes the firestore changes with Firebase. Were you using this version prior to upgrading NativeScript to 3.4? Trying to eliminate possible issues here.

If you console log the whole “error” object from the failed promise, does it spit-out any underlying query errors or SDK problems?


#8

Hi @manojdcoder,

I ran the program in debug again and it appears that firebase init is not happening correctly. The authentication module is working and I am able to console.log the user, but after that the connection to firebase reattime db is not working.

Any suggestions…

Thanks


#9

Hi @sean-perkins,

I am using 3.1.2 version of the plugin with NS 3.3.
When I upgraded to NS 3.4, I couldn’t get the app to work with the 3.1.2 version of the plugin (same issue of firebase query not working),
I then decided to upgrade the plugin to the latest 5.0.5 to see if it work with this. However the same issue is occurring there.

I consoled the error and this what I got

Error in firebase.query: TypeError: Cannot read property 'child' of null
JS: TypeError: Cannot read property 'child' of null
JS: ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'value' of undefined
JS: TypeError: Cannot read property 'value' of undefined
JS:     at file:///data/data/org.nativescript.qbank/files/app/login/login.component.js:135:23
JS:     at ZoneDelegate.invoke (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:365:26)
JS:     at Object.onInvoke (file:///data/data/org.nativescript.qbank/files/app/tns_modules/@angular/core/bundles/core.umd.js:4156:37)
JS:     at ZoneDelegate.invoke (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:364:32)
JS:     at Zone.run (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:125:43)
JS:     at file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:760:57
JS:     at ZoneDelegate.invokeTask (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:398:31)
JS:     at Object.onInvokeTask (file:///data/data/org.nativescript.qbank/files/app/tns_modules/@angular/core/bundles/core.umd.js:4147:37)
JS:     at ZoneDelegate.invokeTask (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:397:36)
JS:     at Zone.runTask (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:165:47)
JS:     at drainMicroTaskQueue (file:///data/data/org.nativescript.qbank/files/app/tns_modules/nativescript-angular/zone-js/dist/zone-nativescript.js:593:35)

#10

Can you share the section of code where you are initializing firebase? Normally you get null back in the error block when it’s either an invalid path, you aren’t authorized to that key or the connection is off. All of which should throw a larger error, but they could be getting consumed by a catch block.

Also, is the data you are accessing, requiring the user to be authorized? Your stacktrace has changed slightly, as I imagine you are testing other parts of your app.


#11

Hi @sean-perkins,

Thanks - you and @manojdcoder pointed me in the right direction. The problem was that I was that firebase was not initialising. I solved this by putting firebase init in a timeout.

And yes the stack trace changed because I was testing other parts of the app :slight_smile:


#12

hi folks.
I have an issue related to firebase,
after installing firebase plugin :

Could not resolve all dependencies for configuration ‘:_F0F1F2DebugApkCopy’.
Could not find :nativescript-optimized:.
Required by:
project :

can anyone help me with this