gaearon / react-hot-loader

Tweak React components in real time. (Deprecated: use Fast Refresh instead.)
http://gaearon.github.io/react-hot-loader/
MIT License
12.26k stars 801 forks source link

(0 , _reactHotLoader.hot) is not a function #880

Closed WickedSik closed 6 years ago

WickedSik commented 6 years ago

If you are reporting a bug or having an issue setting up React Hot Loader, please fill in below. For feature requests, feel free to remove this template entirely.

Description

What you are reporting:

When runnin npm run hot (cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js) it compiles fine: DONE Compiled successfully in 14861ms.

However when I got to the page, I get greeted by an error in the console and a blank page.

[HMR] Waiting for update signal from WDS...

app.js:229902 Uncaught TypeError: (0 , _reactHotLoader.hot) is not a function
    at Object.<anonymous> (app.js:229902)
    at Object../resources/assets/js/containers/App.js (app.js:229934)
    at __webpack_require__ (app.js:708)
    at fn (app.js:113)
    at Object../resources/assets/js/app.js (app.js:226100)
    at __webpack_require__ (app.js:708)
    at fn (app.js:113)
    at Object.0 (app.js:247692)
    at __webpack_require__ (app.js:708)
    at ./node_modules/add-dom-event-listener/lib/EventBaseObject.js.Object.defineProperty.value (app.js:806)
(anonymous) @ app.js:229902
./resources/assets/js/containers/App.js @ app.js:229934
__webpack_require__ @ app.js:708
fn @ app.js:113
./resources/assets/js/app.js @ app.js:226100
__webpack_require__ @ app.js:708
fn @ app.js:113
0 @ app.js:247692
__webpack_require__ @ app.js:708
./node_modules/add-dom-event-listener/lib/EventBaseObject.js.Object.defineProperty.value @ app.js:806
(anonymous) @ app.js:809

app.js:199173 XHR finished loading: GET "http://localhost:8080/sockjs-node/info?

app.js:205943 [WDS] Hot Module Replacement enabled.

tag_assistant_compiled.js:120 XHR finished loading: GET "http://localhost:8080/js/app.js".

Expected behavior

What you think should happen:

A working HMR situation 😄

Actual behavior

What actually happens:

The above error.

Environment

React Hot Loader version: 3.1.3

Run these commands in the project folder and fill in their results:

  1. node -v: 8.1.3
  2. npm -v: 5.6.0

Then, specify:

  1. Operating system: Mac OS X (latest)
  2. Browser and version: Chrome (latest)

Reproducible Demo

Unfortunately I am not at liberty to share the code we're using, so I must take a raincheck on this. However, I can tell the following:

We're running laravel v5.5 + mix v1.7.2 + react v15.6.2

webpack.mix.js

const mix = require('laravel-mix');

mix.webpackConfig({
    resolve: {
        alias: {
            'actions': path.resolve(__dirname, 'resources/assets/js/actions'),
            'assets': path.resolve(__dirname, 'resources/assets/js/assets'),
            'components': path.resolve(__dirname, 'resources/assets/js/components'),
            'constants': path.resolve(__dirname, 'resources/assets/js/constants'),
            'containers': path.resolve(__dirname, 'resources/assets/js/containers'),
            'reducers': path.resolve(__dirname, 'resources/assets/js/reducers'),
            'routes': path.resolve(__dirname, 'resources/assets/js/routes'),
            'stores': path.resolve(__dirname, 'resources/assets/js/stores'),
            'styles': path.resolve(__dirname, 'resources/assets/js/styles'),
            'middleware': path.resolve(__dirname, 'resources/assets/js/middleware'),
            'api': path.resolve(__dirname, 'resources/assets/js/api')
        }
    }
});

mix.react('resources/assets/js/app.js', 'public/js')

if (mix.inProduction()) {
    mix.version();
}

Relevant code:

import React, { Component } from "react";
import { connect } from "react-redux";
import classnames from "classnames";
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider";
import getMuiTheme from "material-ui/styles/getMuiTheme";
import { Route, Switch, Redirect } from "react-router-dom";

import MainApp from "routes/app/";
import Page404 from "routes/404/";
import Page500 from "routes/500/";
import PageConfirmEmail from "routes/confirm-email/";
import PageForgotPassword from "routes/forgot-password/";
import PageResetPassword from "routes/reset-password/";
import PageFullscreen from "routes/fullscreen/";
import PageLockScreen from "routes/lock-screen/";
import PageLogin from "routes/login/";
import PageSignUp from "routes/sign-up/";
import { push } from "react-router-redux";
import { hot } from 'react-hot-loader'

// = styles =
// 3rd
import "styles/bootstrap.scss";
// custom
import "styles/layout.scss";
import "styles/theme.scss";
import "styles/ui.scss";
import "styles/app.scss";

import lightTheme from "./themes/lightTheme";
import darkTheme from "./themes/darkTheme";
import grayTheme from "./themes/grayTheme";

class App extends Component {
  componentDidMount() {
  }

  render() {
    const {
      match,
      location,
      layoutBoxed,
      navCollapsed,
      navBehind,
      fixedHeader,
      sidebarWidth,
      theme,
      isLoggedIn,
      hasChosenRole
    } = this.props;
    let materialUITheme;
    switch (theme) {
      case "gray":
        materialUITheme = grayTheme;
        break;
      case "dark":
        materialUITheme = darkTheme;
        break;
      default:
        materialUITheme = lightTheme;
    }

    const isRoot = location.pathname === "/" ? true : false;
    if (isRoot) {
      return <Redirect to={"/app/dashboard"} />;
    }

    return (
      <MuiThemeProvider muiTheme={getMuiTheme(materialUITheme)}>
        // ... more
      </MuiThemeProvider>
    );
  }
}

const mapStateToProps = (state, ownProps) => {

  return {
    layoutBoxed: state.settings.layoutBoxed,
    navCollapsed: state.settings.navCollapsed,
    navBehind: state.settings.navBehind,
    fixedHeader: state.settings.fixedHeader,
    sidebarWidth: state.settings.sidebarWidth,
    theme: state.settings.theme,
    isLoggedIn: state.workspaces.fetched && state.user.isLoggedIn,
    hasChosenRole: state.workspaces.fetched && state.workspaces.list.length > 0
  };
};

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    redirectTo: route => dispatch(push(route))
  };
};

App = connect(mapStateToProps, mapDispatchToProps)(App);
export default hot(module)(App)
WickedSik commented 6 years ago

Babel.js

{
  "presets": [
    "es2015",
    "react",
    "stage-2"
  ],
  "plugins": [
    "syntax-dynamic-import",
    "transform-decorators-legacy",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ],
  "env": {
    "test": {
      "plugins": [
        "transform-decorators-legacy",
        "transform-object-rest-spread",
        "istanbul"
      ]
    }
  }
}
WickedSik commented 6 years ago

I did a little test.

Old:

App = connect(mapStateToProps, mapDispatchToProps)(App);
export default hot(module)(App)

New:

if(module.hot) {
  module.hot.accept();
}
export default App

This does compile well (I presume module.hot doesn't exist), and runs on the page, but modules aren't reloaded.

gregberge commented 6 years ago

You are not using the good version of React Hot Loader. hot is only available since v4. Upgrade react-hot-loader and it should work.