react-hot-loader: "Can't make class hot reloadable due to being read-only”

I’m getting the "Can’t make class hot reloadable due to being read-only” warning on three of my components. Considering that these are ordinary components, I am a bit confused by this error; it seems random. Any ideas what could have gone wrong?

Here is an example of one such component that is throwing the error. The other two components are reasonably similar to this one:

import React, { Component } from 'react';
import { View } from 'components/layout';
import { RegisterForm } from './components';

const viewConfig = {
  ...
};

export default class RegisterView extends Component {
  render() {
    return (
      <View {...viewConfig}>
        <RegisterForm />
      </View>
    );
  }
}

EDIT:

Looks like this is connected to #72?

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 34 (10 by maintainers)

Commits related to this issue

Most upvoted comments

I too was getting this issue. After reading comments above i fixed it by doing following thing

/* file a.js */
export default x;

/* file index.js */
//previously
// export {default as x} from a;
//now
export x from a;

Useful link - https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0#.rvrx62s5p

And FYI the links in the warning are incorrect: http://babeljs.io/docs/advanced/loose/ is 404 http://babeljs.io/docs/usage/options/ doesn’t mention loose mode

After a lot of head-banging, we replaced

export {default as SampleOne} from './SampleOne/SampleOne';
export {default as SampleTwo} from './SampleTwo/SampleTwo';

with

import {default as SampleOne} from './SampleOne/SampleOne';
import {default as SampleTwo} from './SampleTwo/SampleTwo';

export {SampleOne, SampleTwo};

and that seems to be working for us.

Remove warnings:

  1. Don’t reexport. OR
  2. Use CommonJS export (module.exports) OR
  3. Use plugin for babel babel-plugin-add-module-exports

I was also experiencing this. The warning goes away when I stop using an index file to reexport things in bulk.

tl;dr: export {default as FooComponent} from './FooComponent' is what breaks things.

Setup

Given a filesystem like so:

└─┬ client
  └─┬ components
    ├── index.js
    └─┬ Spinner
      └── index.jsx

with client/components/index.js:

export {default as Spinner} from './Spinner'
// ... more lines like that

With webpack’s resolve.root pointing at client/, I’d import components elsewhere like so

import { Spinner } from 'components'

And get the warning about Spinner being readonly.

The fix

Alter client/component/index.js to export things like so:

import {default as Spinner} from './Spinner'

module.exports = {
  Spinner
}

Edit: no circular imports

This approach works okay but you can’t do the following inside a component:

import {SomeOtherComponent} from 'components'

Instead, load the desired component directly:

import SomeOtherComponent from 'components/SomeOtherComponent'

Have tried all the solutions in this thread, nothing works to remove the warning. However, hot reloading is working as expected for the relevant components.

Another solution is

export default {
  Component1: require('./Component1'),
  Component2: require('./Component2'),
  ...
}

Instead of having to update both import and export sections, each component has one line.

@gaearon - curious, is 3.0 going to solve that?

I ran into this issue, and it’s happening in a super confusing way. When I created a Main file to centralize all my exports for a particular widget, I did this:

export {default as actionCreators} from "./actions.js";
export {default as reducers} from "./reducers.js";
export {default as QueryEditor} from "./view.jsx";
export {ReduxQueryEditor, ReactQueryEditor} from "./renderers.jsx";

(ReduxQueryEditor, in this case, being the result of React.createClass and everything else being either a function or an object)

The warning I got wasn’t on any of the default as blah stuff I was exporting. I got the warning on ReduxQueryEditor.

I was able to fix it like this:

import {ReduxQueryEditor} from "./renderers.jsx";
export {ReduxQueryEditor}

This is really confusing though. I’m exporting defaults from other modules, not from that one.