简体   繁体   中英

Meteor session is undefined after page redirect

I am making a game that requires a lobby of players, but no accounts. Kind of like the game, Spyfall . I am using Meteor Sessions to know which player joined the lobby so that I can return the proper data for that specific player. I have a join.js component where the user enters in the lobby access code and the user's name. This component also redirects the user to the lobby. Join.js is at the route, /join, and the lobbies are at the route, /:lobby. Here is the join.js handleSubmit method which takes the user input and puts it in the players collection:

    handleSubmit(event) {
    event.preventDefault();
    var party = Players.findOne({code: this.refs.code.value});
    if(typeof party !== 'undefined') {
        Meteor.call('players.insert', this.refs.code.value, this.refs.name.value);
        var playerId = Players.findOne({"name": this.refs.name.value})._id;
        Meteor.call('players.current', playerId);
        location.href = "/" + this.refs.code.value;
    } else {
        document.getElementById("error").innerHTML = 'Please enter a valid party code';
    }

I am using Sessions in the Meteor.methods in the players.js collection to get the current user.

import { Mongo } from 'meteor/mongo';
import { Session } from 'meteor/session';

Meteor.methods({
    'players.insert': function(code, name) {
        console.log('adding player: ', name , code);
        Players.insert({code: code, name: name});
    },
    'players.updateAll': function(ids, characters, banners, countries, ancestors) {
        for (var i = 0; i < characters.length; i++){
            Players.update({_id: ids[i]}, {$set: {character: characters[i], banner: banners[i], country: countries[i], ancestor: ancestors[i]},});
        }
    },
    'players.current': function(playerId) {
            Session.set("currentPlayer", playerId);
            console.log(Session.get("currentPlayer"));
    },
    'players.getCurrent': function() {      
            return Session.get("currentPlayer");
    }
});

export const Players = new Mongo.Collection('players');

The console.log in the 'players.current' method returns the proper player id, but once the page redirects to /:lobby, the players.getCurrent returns undefined. I want players.getCurrent to return the same value that the console.log returns. How do I fix this issue? This is the function to get the current player id in the lobby.js:

getCurrentPlayerId() {
    return Meteor.call('players.getCurrent');
}

Per the Meteor API , Meteor methods are meant to be the way you define server side behavior that you call from the client. They are really intended to be defined on the server.

Methods are remote functions that Meteor clients can invoke with Meteor.call.

A Meteor method defined on the client simply acts as a stub.

Calling methods on the client defines stub functions associated with server methods of the same name

Based on your code it looks like you are doing everything client side. In fact, session is part of the Meteor client API (can't use on the server).

Session provides a global object on the client that you can use to store an arbitrary set of key-value pairs.

Therefore, If I were you, I would just implement all this logic in some sort of util file that you can then import into the Templates where you need it. You are effectively doing the same thing, you just need to use regular functions instead of Meteor methods.

Here is an example util file (be sure to update the Players import based upon your project's file structure).

import { Players } from './players.js';
import { Session } from 'meteor/session';

export const players = {
  insert: function(code, name) {
    console.log('adding player: ', name , code);
    return Players.insert({code: code, name: name});
  },

  updateAll: function(ids, characters, banners, countries, ancestors) {
    for (var i = 0; i < characters.length; i++) {
      Players.update({_id: ids[i]}, {$set: {character: characters[i], banner: banners[i], country: countries[i], ancestor: ancestors[i]},});
    }
  },

  setCurrent: function(playerId) {
    Session.set("currentPlayer", playerId);
    console.log(Session.get("currentPlayer"));
  },

  getCurrent: function(unixTimestamp) {
    return Session.get("currentPlayer");
  },
};

Then, you can import this into whatever template you have that has defined the event handler you included in your question.

import { Template } from 'meteor/templating';
import { players } from './utils.js';

Template.template_name.events({
  'click .class': handleSubmit (event, instance) {
    event.preventDefault();
    var party = Players.findOne({code: this.refs.code.value});

    if (typeof party !== 'undefined') {
        var playerId = players.insert(this.refs.code.value, this.refs.name.value);
        players.setCurrent(playerId);
        location.href = "/" + this.refs.code.value;
    } else {
        document.getElementById("error").innerHTML = 'Please enter a valid party code';
    }
  },
});

Of course you will need to modify the above code to use your correct template name and location of the utils file.

I think the issue is that you are using

location.href = "/" + this.refs.code.value;

instead of using

Router.go("/"+this.refs.code.value);

if using Iron Router. Doing this is as if you are refreshing the page. And here's a package to maintain Session variables across page refreshes .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM