Instantsearch.js: setImmediate is not defined on Meteor + React

Created on 5 Jan 2017  Â·  9Comments  Â·  Source: algolia/instantsearch.js

react-instantsearch: 2.1.0
Latest versions of Chrome and FF.

Hello, I've just started setup react-instantsearch on my Meteor project and have strange bug.

I'm following steps from the React Instant Search Getting Started Tutorial and when I insert first widget (<Hits /> for example) I have an error in console:

modules.js?hash=35e875d…:110624 Uncaught ReferenceError: setImmediate is not defined
    at scheduleUpdate (modules.js?hash=35e875d…:110624)
    at Object.registerWidget (modules.js?hash=35e875d…:110633)
    at new Connector (modules.js?hash=35e875d…:109693)
    at modules.js?hash=35e875d…:11541
    at measureLifeCyclePerf (modules.js?hash=35e875d…:11321)
    at ReactCompositeComponentWrapper._constructComponentWithoutOwner (modules.js?hash=35e875d…:11540)
    at ReactCompositeComponentWrapper._constructComponent (modules.js?hash=35e875d…:11526)
    at ReactCompositeComponentWrapper.mountComponent (modules.js?hash=35e875d…:11434)
    at Object.mountComponent (modules.js?hash=35e875d…:4461)
    at ReactDOMComponent.mountChildren (modules.js?hash=35e875d…:10623)

It refers to this code:

exports.default = createWidgetsManager;                                                                                // 6
function createWidgetsManager(onWidgetsUpdate) {                                                                       // 7
  var widgets = [];                                                                                                    // 8
  // Is an update scheduled?                                                                                           // 9
  var scheduled = false;                                                                                               // 10
                                                                                                                       // 11
  // The state manager's updates need to be batched since more than one                                                // 12
  // component can register or unregister widgets during the same tick.                                                // 13
  function scheduleUpdate() {                                                                                          // 14
    if (scheduled) {                                                                                                   // 15
      return;                                                                                                          // 16
    }                                                                                                                  // 17
    scheduled = true;                                                                                                  // 18
    setImmediate(function () {                                                                                         // 19
      scheduled = false;                                                                                               // 20
      onWidgetsUpdate();                                                                                               // 21
    });                                                                                                                // 22
  }                    
Question

All 9 comments

Hi @Kolyasya,

Currently we are using setImmediate to perform some scheduling and it seems that this function isn't available with meteor. We are going to change this code to be compatible with the largest lib, but in the meantime one thing you can do is using a setImmediatepolyfill like this one: https://github.com/YuzuJS/setImmediate. I tried it with a small meteor app and it seems to work fine.

Also you are going to have another issue because of the algoliaClient we use under the hood of react-instantsearch. To bypass this issue, you can retrieve the algoliaSearch client like describe here https://github.com/algolia/algoliasearch-client-javascript/issues/292 and use the algoliaClientprop on the <InstantSearch/> component to instantiate it.

Here a working example:

import algoliaClient from 'algoliasearch/src/browser/builds/algoliasearch'

<InstantSearch
        indexName="xxx"
        algoliaClient={algoliaClient('appId', 'apiKey')}
      >
</InstantSearch>

Let me know if this help :)

@mthuret thank you for a detailed answer, it helped :-) All works as it should now!

That's great to hear @Kolyasya!

@mthuret and @Kolyasya: I'm trying to use <InstantSearch /> in a Meteor project but suspect the fix/workaround listed above doesn't work.

Passing the algoliaClient prop doesn't get around the problem of Meteor importing the wrong package as InstantSearch's dom.js still imports algoliasearch which causes the Meteor build system (any build system that doesn't understand the object form of the browser section of package.json) to import the Node version of the package.

Is it possible to use InstantSearch in Meteor?

Would it be possible to change dom.js to import algoliasearch/src/browser/builds/algoliasearch (or even .../algoliasearchLite) instead as the name dom.js would imply it's always going to be running in a browser?

I can confirm that changing import algoliasearch from 'algoliasearch' in dom.js to import algoliasearch/src/browser/builds/algoliasearch instead gets this working in Meteor.

We are no more using setImmediate in react-instantsearch, @damonmaria what you are experiencing is due to https://github.com/algolia/instantsearch.js/issues/1024#issuecomment-221618284

This is a meteor.js issue for now. I bet you could also fix it by tuning your build tool to alias algoliasearch to build/algoliasearch somehow?

Thanks @vvo. Yes, I knew the Meteor deficiency in handling the package.json browser field was going to be the problem. But I thought the 2nd paragraph in this comment above was referring to a way around that Meteor issue. If it is supposed to be a way around that issue then it doesn't work as the import of algoliasearch is still there to provide a default value.

For the moment I have forked this package and changed the require to use algoliasearch/src/browser/build/algoliasearchLite.js instead of algoliasearch. My further question was could this same change be done in the package itself? Or is dom.js used in SSR and therefore the browser specific path can't be used.

Or is dom.js used in SSR and therefore the browser specific path can't be used.

We do not yet have good SSR in react-instantsearch so I bet we could ultimately make this change but it won't be 100% future proof because ultimately we will get server side rendering and the fix will have to be reverted. I'd rather see meteor.js take action or someone (maybe you) do the necessary changes in meteor.js to handle the browser field on packages.

Meteor.js fully implementing use of the browser field would be best. Meteor already handles a browser field that specifies a different main file, but it does not handle the object form of browser which specifies individual files to replace. I did bit of an investigation to see if it was an easy win but no. Replacing just the main file is pretty simple. Replacing individual files are they're required would be a challenge in understanding the Meteor build process that I'm not up to.

Was this page helpful?
0 / 5 - 0 ratings