facebook / react

The library for web and native user interfaces.
https://react.dev
MIT License
225.37k stars 45.95k forks source link

Rendering with `process.env.NODE_ENV = 'production';` #4765

Closed zerkms closed 8 years ago

zerkms commented 8 years ago

React v0.13.3

Code to reproduce the problem:

process.env.NODE_ENV = 'production';

class Foo extends Component {
    render() {
        return <div>foo</div>;
    }
}

React.render(
    <Foo />,
    document.getElementById('app')
);

When is run the Uncaught TypeError: Cannot set property 'props' of undefined error is thrown with the following callstack:

    function defineWarningProperty(object, key) {
      Object.defineProperty(object, key, {

        configurable: false,
        enumerable: true,

        get: function() {
          if (!this._store) {
            return null;
          }
          return this._store[key];
        },

        set: function(value) {
          ("production" !== process.env.NODE_ENV ? warning(
            false,
            'Don\'t set the %s property of the React element. Instead, ' +
            'specify the correct value when initially creating the element.',
            key
          ) : null);
          this._store[key] = value; // <--- this line
        }

      });
    }

which is invoked from

    var ReactElement = function(type, key, ref, owner, context, props) {
      // Built-in properties that belong on the element
      this.type = type;
      this.key = key;
      this.ref = ref;

      // Record the component responsible for creating this element.
      this._owner = owner;

      // TODO: Deprecate withContext, and then the context becomes accessible
      // through the owner.
      this._context = context;

      if ("production" !== process.env.NODE_ENV) {
        // The validation flag and props are currently mutative. We put them on
        // an external backing store so that we can freeze the whole object.
        // This can be replaced with a WeakMap once they are implemented in
        // commonly used development environments.
        this._store = {props: props, originalProps: assign({}, props)};

        // To make comparing ReactElements easier for testing purposes, we make
        // the validation flag non-enumerable (where possible, which should
        // include every environment we run tests in), so the test framework
        // ignores it.
        try {
          Object.defineProperty(this._store, 'validated', {
            configurable: false,
            enumerable: false,
            writable: true
          });
        } catch (x) {
        }
        this._store.validated = false;

        // We're not allowed to set props directly on the object so we early
        // return and rely on the prototype membrane to forward to the backing
        // store.
        if (useMutationMembrane) {
          Object.freeze(this);
          return;
        }
      }

      this.props = props; // <--- this line
    };

So as we can see - this._store is only defined when it's not in production mode, but it's still being addressed.

Am I missing something?

zpao commented 8 years ago

React does initialization based on the environment. So after you require/import React, the environment at that point should never change. We don't handle the changing case and we likely never will.

The suggested way to make use of NODE_ENV is via an environment variable NODE_ENV=production node app.js. If that's not possible, then ensuring that process.env.NODE_ENV='production' ASAP in your app, before you require/import.

zerkms commented 8 years ago

Cool, thanks.