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

"Reference Error: React is not defined" with server side rendering. How to implement in an isomorphic context? #31

Open
tconroy opened this issue Aug 4, 2016 · 22 comments

Comments

@tconroy
Copy link

tconroy commented Aug 4, 2016

Hi!

This is likely just a configuration issue on my part, but I'm getting the following error message when attempting to use this loader in an isomorphic react app:

error:

/Users/Tom/Code/src/svg/circle.inline.svg:3
React.createElement(
^

ReferenceError: React is not defined
    at Object.<anonymous> (circle.inline.svg:1:1)
    at Module._compile (module.js:413:34)
    at loader (/Users/Tom/Code/node_modules/babel-register/lib/node.js:148:5)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/Tom/Code/node_modules/babel-register/lib/node.js:158:7)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Module.require (module.js:367:17)
    at require (internal/module.js:16:19)
    at Object.<anonymous> (BlockAdComponent.js:3:1)
    at Module._compile (module.js:413:34)

webpack loader config:

      {
        test: /\.inline.svg$/,
        loader: 'babel!svg-react',
      },

contents of SVG file:

<svg
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  x="0px"
  y="0px"
  viewBox="0 0 100 100"
  enable-background="new 0 0 100 100"
>
  <circle
    className="svg-inline-circle"
    cx="50"
    cy="50"
    r="48"
  >
  </circle>
</svg>

simplified example of how the SVG is being imported:

import React from 'react';
import Circle from 'svg/circle.inline.svg';

class BlockComponent extends React.Component {

  render() {
    const { config, swipeArrows } = this.props;
    return (
      <div>
        <Circle className="block-ad__circle" />
      </div>
    );
  }
}

export default BlockComponent;

The setup instructions I followed were from this guide (method 2)

Environment is:
Node: 5.5.0
NPM: 2.15.9
Webpack: 1.13.1
React: 0.14.0
svg-react-loader: 0.3.7
Express: 4.14.0

A coworker had this working on his local via a simple webpack-dev-server, however while attempting to implement it into an isomorphic react context (express server backened), I am now getting this error.

If you need any other info from me please feel free to ask. Any help much appreciated.

@tconroy tconroy changed the title "Reference Error: React is not defined" with server side rendering. "Reference Error: React is not defined" with server side rendering. How to implement in an isomorphic context? Aug 8, 2016
@tconroy
Copy link
Author

tconroy commented Aug 8, 2016

Any ideas? Think the root issue is it's unclear how to implement this in an isomorphic (server side) environment.

@jhamlet
Copy link
Owner

jhamlet commented Aug 8, 2016

@tconroy can you get a look at the transpiled source of circle.inline.svg and post it here?

@tconroy
Copy link
Author

tconroy commented Aug 8, 2016

@jhamlet sure -- I believe this is it, ripped from the bundle file (please let me know if you need any more samples :) ):

/***/ },
/* 137 */
/***/ function(module, exports, __webpack_require__) {

    'use strict';

    var React = __webpack_require__(11);
    var helpers = __webpack_require__(138)(__webpack_require__(139));

    module.exports = React.createClass({

        displayName: "CircleInline",

        getDefaultProps: function getDefaultProps() {
            return { "version": "1.1", "xmlns": "http://www.w3.org/2000/svg", "x": "0px", "y": "0px", "viewBox": "0 0 100 100", "enableBackground": "new 0 0 100 100" };
        },
        componentDidMount: function componentDidMount() {
            helpers.applyXmlAttributes(this);
        },
        render: function render() {
            var props = this.props;
            var children = props.children;

            return React.createElement(
                'svg',
                this.props,
                React.createElement('circle', { className: 'svg-inline-circle', cx: '50', cy: '50', r: '48' }),
                React.Children.map(children, function (c) {
                    return c;
                })
            );
        }
    });

/***/ },

@jhamlet
Copy link
Owner

jhamlet commented Aug 8, 2016

Interesting. You're getting the error on the React.createElement call... not on the createClass call...

In that same source what is /* 11 */ pointing to (I'm assuming its react).

Are you using React in other places (again, I would assume so)? Are they pulling in the same module number (11)?

Something to try: In your node_modules/svg-react-loader/utility/template.txt can you add a line after var children = props.children in the render() method:

var React = require('react');

@tconroy
Copy link
Author

tconroy commented Aug 8, 2016

@jhamlet: first off -- thank you for your help. hope we can solve this!

/* 11 */ does seem to point to React, and is required extensively throughout the app. I found 30+ references to it. Here is how it is defined:

/* 11 */
/***/ function(module, exports) {

    module.exports = require("react");

/***/ },

I've added in an example implementation to my original post (at the end) showing how I'm actually using the SVG inside a component ( pretty basic ).

Adding the React require to template.txt resulted in the same error (ReferenceError: React is not defined).

@tconroy
Copy link
Author

tconroy commented Aug 8, 2016

so some minor clarification / correction on my part:

The error is occurring when I try to run our start-dev NPM command. That command looks like this:

"start-dev": "NODE_ENV=dev APP_API_HOST=http://api.domain.com/ APP_STATS_API_HOST=http://statsapi.domain.com:8080 babel-node ./src/server.js",

src/server.js contains the Express server, that does the server-side rendering for the React client.

We have a separate build command, npm run build:server, which produces the transpiled source shared above. That command looks like this:

"build:server": "webpack --config ./cfg/server.js",

I'm not sure how to provide the transpiled source for npm run start-dev since its a server. it is using webpackDevMiddleware with the dev webpack config, which does include svg-react-loader.

@jhamlet
Copy link
Owner

jhamlet commented Aug 8, 2016

Interesting.

Are you pre-compiling with webpack before this step?

@jhamlet
Copy link
Owner

jhamlet commented Aug 9, 2016

Not sure what to say, or where to go from here...

Is it possible you can create a stripped-down version of your project that reproduces this issue? With that I can then do some debug-runs on my end.

@tconroy
Copy link
Author

tconroy commented Aug 9, 2016

Hi @jhamlet -- no, no pre-compiling with webpack prior to this step. I will try and create a stripped down version when I have some time this weekend. Thank you for your help.

@jhamlet
Copy link
Owner

jhamlet commented Aug 10, 2016

@tconroy on another note: I'm getting ready to publish v0.4.0 as latest. You can try it out with npm install svg-react-loader@next and see if the problem goes away (I removed the need for the babel compiler).

@tconroy
Copy link
Author

tconroy commented Aug 10, 2016

@jhamlet good to know, thanks. I'll give it a shot. My guess was this issue was being caused somewhere in the babel transpiration so maybe that'll help. For the time being I had to unfortunately remove the loader from the project but really hoping to add it back since it works so well.

@jhamlet
Copy link
Owner

jhamlet commented Aug 24, 2016

@tconroy Any progress on this? Did v0.4.0 solve the problem? Did you get the chance to create a smaller sample repo that reproduces the issue?

@tconroy
Copy link
Author

tconroy commented Aug 24, 2016

hi @jhamlet -- apologies for the delay, been busy and haven't gotten around to this since removing from the project. will keep you posted!

@jblok
Copy link

jblok commented Nov 2, 2016

Hi @jhamlet - First off, thank you for your efforts on this loader!

I am getting this same error when running tests with Mocha. My Mocha config is

mocha tools/test-setup.js \"src/**/*.spec.js\" --reporter progress --compilers js:babel-register

It doesn't happen when running the application, just the tests. Version 0.4.0-beta2 didn't fix the issue.

Just wondering if you had had any further thoughts on this issue since August? Thanks very much :)

@jblok
Copy link

jblok commented Nov 2, 2016

OK, I worked it out. When testing with Mocha, it's not even using the webpack config. So mocha on it's own just doesn't know how to handle a raw SVG file being imported as it isn't a javascript file. I don't quite understand why it was failing on React.createElement within the SVG as that kind of implies the loader has converted it, but can't find a dependency? Perhaps the error isn't correct?

Either way, I found 2 ways around it. Option 1 is to use mocha-webpack and compile everything with webpack before testing. I didn't go down that path though.

Option 2 is what I have done and is to remove the SVG extension from those that are imported with mocha and use babel-plugin-rewire to overwrite the import statement for the SVG. The whole thing looks like this now:

  • My mocha command in package.json

"test": "mocha tools/test-setup.js \"src/**/*.spec.js\" --reporter progress"

  • My test-setup.js file
require('babel-register')({
  plugins: ['babel-plugin-rewire']
})
require.extensions['.svg'] = () => null;
  • Then in a test file, then do something like...
import ComponentUnderTest from './ComponentUnderTest'
ComponentUnderTest.__Rewire__('SVGImport', () => <p>SVGPlaceholder</p>);

@onvno
Copy link

onvno commented Aug 23, 2017

meet this problem,try:

plugins: [
  new webpack.ProvidePlugin({
    "React": "react",
  }),
],

@alexcastillo
Copy link

Thanks @onvno!

@mascardoso
Copy link

Hi there. I don't use svg-react-loader but instead svg-sprite-loader. Nevertheless I see that both are bringing the same issues... @tconroy did you manage after all fix your issue. I also use a isomorphic app and I'm getting the same error:

[0]     "stack": [
[0]       "ReferenceError: React is not defined",
[0]       "    at Object.<anonymous> (/front/assets/img/sprite.svg:1:1)",
[0]       "    at Module._compile (module.js:571:32)",
[0]       "    at loader (/node_modules/babel-register/lib/node.js:144:5)",
[0]       "    at Object.require.extensions.(anonymous function) [as .js] (/node_modules/babel-register/lib/node.js:154:7)",
[0]       "    at Module.load (module.js:488:32)",
[0]       "    at tryModuleLoad (module.js:447:12)",
[0]       "    at Function.Module._load (module.js:439:3)",
[0]       "    at Module.require (module.js:498:17)",
[0]       "    at require (internal/module.js:20:19)",

Webpack config:

..
      {
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: path.resolve(__dirname, 'front/assets/img/')
      }
..

jsx-1:

import React from 'react'
import '../../../assets/img/sprite.svg'

const Icon = ({ type, fill, size, padded, id }) => (
  <svg ...>
    <use xlinkHref={`#sprite-${type}`} />
  </svg>
)

export default Icon

jsx-2:

import Icon from '../icon.jsx'

<Icon type='customize' size='--medium' />

Any help would be extremely appreaciated.

@stereobooster
Copy link

Here is reproducible example https://github.com/stereobooster/comparison/tree/aphrodite-ssr

git clone https://github.com/stereobooster/comparison.git
cd comparison/examples
yarn install
cd aphrodite
yarn server

ReferenceError: React is not defined
    at Object.<anonymous> (comparison/examples/shared/assets/reply.svg:1:1)

Also requires babel-node (facepalm)

@Andrew-Dyachenko
Copy link

@onvno Yep, it's working
img-2018-06-04-02-36-24

@NorbertNader
Copy link

NorbertNader commented Sep 28, 2018

Similar issue with svg-sprite-loader. I found a solution that I think might help JetBrains/svg-sprite-loader#40

@hytStart
Copy link

hytStart commented Jun 8, 2020

meet this problem,try:

plugins: [
  new webpack.ProvidePlugin({
    "React": "react",
  }),
],

excuse me, can you tell me the reason

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

10 participants