Search code examples
meteoriron-routerminimongo

How can I avoid an infinite loop in my meteor router?


I'm building an online store in meteor where customers can customize products in the store. I have setup a client-only collection called Inventory which stores all the product data and is updated accordingly in response to user input. Once the user is ready to checkout, I dump the product data into a client & server side collection called ShoppingCart. I want to allow users to go back and revise their edits on the product in Inventory so I setup my router to $set data from the ShoppingCart into Inventory if it finds a match:

Router.route '/:_type/:_id', ->
  Session.set "inCart", false
  @render @params._type, 
    data: =>
      storedItem = ShoppingCart.findOne {
        userId: Meteor.userId(), 
        image: @params._id
      }
      if storedItem?
        delete storedItem._id
        Inventory.update {image: @params._id}, {
          $set: storedItem
        }
      Inventory.findOne image: @params._id

EDIT: This seems to cause my router method to get stuck in an infinite loop whenever data in Inventory changes. Is there any way to avoid this issue? Is there a better way of handling this kind of data altogether that I should consider?


Solution

  • MAJOR CAVEAT - I don't do CoffeeScript, so this is what I can gather having put your code through a compiler.

    I think the problem is that the data function is reactive, and you're updating and returning an item from the Inventory collection within it. Every time the route runs, unless there is no storedItem, it's going to invalidate a computation on which it itself depends and thus rerun again immediately (and subsequently do the same again, etc...).

    As a general rule, I think it's a very bad idea indeed to be updating a collection from within a data function - if you have to do this within the route function, consider the onRun, or onBeforeAction hooks for the update.

    Final thing, just because I don't understand: why do you need to dump the item from the ShoppingCart back into Inventory? Shouldn't it already be there, unless the user has started a new session?