[Solved] In the server this.userId returns undefined when has a logged in user

I was suppose to do this method and unexpectedly felt on an inconvenient trouble by my side.

// /imports/api/usersAdminFieldPublish.js

import { Meteor } from 'meteor/meteor';
import { UsersCollection } from '../collections/users';

Meteor.publish('users.AdminField', function getUserAdminField() {
  if (this.userId) {
    // there's a userId here
    return UsersCollection.usersAdminField();
  } else {
    this.ready();
  }
});


:comet:

// /imports/collections/users.js 

import { Meteor } from 'meteor/meteor';
// there's a logged in user

export const UsersCollection = Object.assign(Meteor.users, {
  usersAdminField() {
    console.log(
      `isServer == ${Meteor.isServer}  && this.userId == ${this.userId}`
    ); // isServer == true  && this.userId == undefined
   
	return this.find(
      { _id: this.userId },
      {
        fields: { admin: 1 },
      }
    );
  },
});

:comet:

// /imports/ui/App.js

import { Meteor } from 'meteor/meteor';
import { useTracker } from 'meteor/react-meteor-data';
import React, { useEffect } from 'react';
import { UsersCollection } from '../collections/users';


export const App = () => {
  const { users } = useTracker(() => {
    const handler = Meteor.subscribe('users.AdminField');

    return {
      isUserReady: handler.ready(),
      users: UsersCollection.usersAdminField(),
    };
  }, []);

  useEffect(() => {
    console.log(users); 
    /* Cursor {collection: LocalCollection, sorter: null, matcher: Matcher, _selectorId: undefined, skip:  0, …}...
  }, [users]); */

  return (
    ...
  );
};

:chess_pawn:
In somehow, am I doing something wrong?
Any help is helpful.
:tent:

I saw 2 this.userId in your codes. One in Meteor.publish('users.AdminField' which is fine.
But the one in your UsersCollection is strange. I don’t think it works like that.

1 Like

Your problem is this
Literally

The trouble is in this custom method:

export const UsersCollection = Object.assign(Meteor.users, {
  usersAdminField() {
    console.log(
      `isServer == ${Meteor.isServer}  && this.userId == ${this.userId}`
    ); // isServer == true  && this.userId == undefined
   
	return this.find(
      { _id: this.userId },
      {
        fields: { admin: 1 },
      }
    );
  },
});

When this function runs, it’s runing with the context of the UsersCollection,
so when it runs this === UsersCollection
Which is why you can run this.find

The easiest way to get what you want is to pass userId into the function as an argument and avoid this except in method and publication function bodies

1 Like

Thank you, @coagmano. I really appreciate it.
:handshake: