Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReferenceError: document is not defined #137

Closed
andrerpena opened this issue Jul 15, 2015 · 14 comments
Closed

ReferenceError: document is not defined #137

andrerpena opened this issue Jul 15, 2015 · 14 comments

Comments

@andrerpena
Copy link

When I try to server render using Node.js + Express + ReactRouter, I get this:

C:\Projects\Git\gearz\node_modules\react-datepicker\node_modules\tether\dist\js\tether.js:406
var el = document.createElement('div');
         ^
ReferenceError: document is not defined

You are assuming document exists, which isn't true when you are server rendering.

The most curious part is that I'm copying my example from the server rendering example. This is how my component looks like:

    var Example = React.createClass({
        getInitialState: function () {
            return {date: moment()};
        },
        onChange: function () {},
        render: function () {
            return React.createElement(
                DatePicker,
                {
                    selected: this.state.date,
                    onChange: this.handleChange
                }
            );
        }
    });

Am I doing anything wrong?

@nadav-dav
Copy link

👍

@ljconde
Copy link

ljconde commented Jul 28, 2015

Getting this same issue still in 0.11..

@RSO
Copy link
Contributor

RSO commented Jul 29, 2015

I'm not really that well versed in the SSR bit, but shouldn't #113 have fixed this?

@gabroe
Copy link

gabroe commented Jul 29, 2015

I'm having the same issue... (node ssr) If I require the datepicker on the server without even using it it shows that error. A workaround I found is that if I require it just before I open the picker I don't see it, in my case I will never render the picker on the server side, so it works.

I tried to locate the issue and seems to be with tether itself,

see:

var transformKey = (function () {
  var el = document.createElement('div');
  var transforms = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
  for (var i = 0; i < transforms.length; ++i) {
    var key = transforms[i];
    if (el.style[key] !== undefined) {
      return key;
    }
  }
})();

That code gets executed when you include tether. Does this have to do anything with the way the datepicker is being bundled with webpack? Sorry I have to do something else so I cant keep digging. If I have time later I'll do it.

@RSO
Copy link
Contributor

RSO commented Aug 3, 2015

Right, I think I know where this issue is coming from. I was a bit confused, as we clearly only load Tether when document is defined, but then I realised that we just figured out that the webpack externals feature has a strange side-effect: if you say you expect a dependency to be global, it will make it global if it isn't already.

I'll have to dig into this, we noticed this @Hacker0x01 when we tried to upgrade and suddenly our underscore was replaced by lodash in the global namespace.

@ljconde
Copy link

ljconde commented Aug 13, 2015

Has there been any progress on this? I'm still getting "document is not defined" when upgrading to 0.11.4, and have to revert to 0.8.0.

@Sridatta7
Copy link

Getting same error in 0.12. Are there any workarounds?

@gabroe
Copy link

gabroe commented Aug 27, 2015

Well, I'm still using it, I just made a fugly workaround, fortunately the component that contains the datepicker has to re-render after some data gets loaded into the page so what I did is if I canUseDom I render the datepicker, otherwise I just render a simple input.

import { canUseDOM } from 'react/lib/ExecutionEnvironment';

...

dateField = function(label, minDate, date, onChange){
    if(canUseDOM){
      var DatePicker = loadDatePicker();
      return <DatePicker
        dateFormat={'MM/DD/YY'}
        minDate={minDate}
        selected={date}
        maxDate={moment().add(1, 'y')}
        placeholderText={label}
        onChange={onChange}
        />;
    }
    return <input
      type='text'
      placeholder={label}
      groupClassName='input-group-sm'/>;
  },
  loadDatePicker = function(){
    if(DP == null){
      DP = require('react-datepicker');
    }
    return DP;
  };

...

<div className='date-field'>
     {dateField('from', moment(), f.getFromDate(), onFromChange)}
</div>

@andrerpena
Copy link
Author

Just out of curiosity... Do you get any error for inconsistency between
whats been rendered on the client and on the server?

Em Qui, 27 de ago de 2015 11:17, Gabriel Espinola notifications@github.com
escreveu:

Well, I'm still using it, I just made a fugly workaround, fortunately the
component that contains the datepicker has to re-render after some data
gets loaded into the page so what I did is if I canUseDom I render the
datepicker, otherwise I just render a simple input.

import { canUseDOM } from 'react/lib/ExecutionEnvironment';

...
dateField = function(label, minDate, date, onChange){
if(canUseDOM){
var DatePicker = loadDatePicker();
return <DatePicker
dateFormat={'MM/DD/YY'}
minDate={minDate}
selected={date}
maxDate={moment().add(1, 'y')}
placeholderText={label}
onChange={onChange}
/>;
}
return ;
},
loadDatePicker = function(){
if(DP == null){
DP = require('react-datepicker');
}
return DP;
};

...

{dateField('from', moment(), f.getFromDate(), onFromChange)}


Reply to this email directly or view it on GitHub
#137 (comment)
.

@vladikoff
Copy link
Contributor

Same error

import DatePicker from 'react-datepicker';

with

          <DatePicker />

Trace:

  [1] [piping] error given was: ReferenceError: document is not defined
  [1]     at /Users/a/b/c/node_modules/react-datepicker/node_modules/tether/dist/js/tether.js:406:12
  [1]     at /Users/a/b/c/node_modules/react-datepicker/node_modules/tether/dist/js/tether.js:415:3
  [1]     at i (/Users/a/b/c/node_modules/react-datepicker/node_modules/tether/dist/js/tether.js:7:22)
[1]     at Object.<anonymous> (/Users/a/b/c/node_modules/react-datepicker/node_modules/tether/dist/js/tether.js:11:2)
[1]     at Module._compile (module.js:460:26)
[1]     at Module._extensions..js (module.js:478:10)
[1]     at Object.require.extensions.(anonymous function) [as .js] (/Users/a/b/c/node_modules/babel-core/lib/api/register/node.js:214:7)
[1]     at Module.load (module.js:355:32)
[1]     at Module._load (module.js:310:12)
[1]     at Function.module._load (/Users/a/b/c/node_modules/piping/lib/launcher.js:32:16)

@Hagbarth
Copy link

To anyone interested I created a small wrapper, that you can import instead of the DatePicker.
It just renders an input field serverside and on the client it passes the props along using ES7 spread syntax.

I just

import {default as DatePicker} from './IsomorphicDatePicker';

And it seems to work fine.

https://gist.github.com/Hagbarth/2eeb59bcbc303313a10e

@gabroe
Copy link

gabroe commented Sep 22, 2015

Thanks!, It looks good, I like to use canUseDom instead of checking for document, my2c

import { canUseDOM } from 'react/lib/ExecutionEnvironment';

@ShardPhoenix
Copy link

I also had this problem when running mocha tests, as the import of Datepicker fails because it tries to access 'document' before jsdom() is called in the test (which is what makes 'document' available). I fixed this by moving the require of Datepicker into the render() method of the component that uses it rather than having it as an import at the top.

@sujaykathrotia
Copy link

Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests