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?
Looking at the loader source, I think this might be connected to the way my modules are exported? Here is an overview of the tree:
├── auth
│ ├── components
│ ├── index.js
│ ├── passwordResetView.js
│ ├── registerView.js
│ ├── signInView.js
│ └── styles.less
// index.js
export { default as PasswordResetView } from './passwordResetView';
export { default as RegisterView } from './registerView';
export { default as SignInView } from './signInView';
import './styles';
Are you using Babel?
Yes, I am.
If you could fork http://github.com/gaearon/react-hot-boilerplate and set up a minimal reproducing example that would be a huge help!
Sure. Here you go: https://github.com/pburtchaell/react-hot-boilerplate

Thanks. I'll take a look with in a few days. In the meantime can you try Babel's loose option? I think it may work if you use loose: ['es6.modules'].
I enabled the loose option and that seems to have fixed it. Guess this would be an issue with Babel then?
Also—since this did fix my issue—it might be worth editing the "Can't make class hot reloadable due to being read-only” warning message from React Hot Loader to mention trying the loose option. I'd be happy to make a PR if you agree.
Not really an issue with Babel, it just tries to follow the spec which disallows overwriting exports. I'm not sure what the right solution is. Maybe it's possible to override them after all—I really don't know property descriptors well. Yeah I would accept a PR.
Cool. PR at #159.
Where do you apply this loose option? the docs linked in #159 no longer exist
I'm wondering this as well, trying to upgrade to Babel 6
@Lordnibbler I tried https://github.com/orlin/babel-preset-es2015-mod which enables loose, this did however not solve my problem. Can you try it out and see if it solves yours, so I can rule out issues in my own config?
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.
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.
Alter client/component/index.js to export things like so:
import {default as Spinner} from './Spinner'
module.exports = {
Spinner
}
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'
Given my relative lack of experience with all of this, I'd welcome a more experienced eye on the suggested setup I'm going with.
Well, module.exports works as you say, but the problem is that it's not ES6. If you import it and then module.exports it, you might as well require it to begin with :)
But it's a workaround, absolutely (given that everything is transpiled.)
@idan's workaround did not fix this issue for me. Neither did use the es2015-mod babel preset. Has anyone figured out something for this?
I'm also having the same issue. I am using an index.jsx file as @idan mentions, so will try to fiddle with that.
Following up — I switched to using react-transform-hmr and it works fine with the export { default as Foo } from './Foo' syntax.
@idan Thanks for your comments here. After fiddling with my exports i got rid of the issue.
for others trying to solve this problem, this is what I got before and after the fix
// export { Button } from './button';
export const Button = require('./button').Button;
any new solution ?
makeExportsHot warning hint not working
currently I am using
import util from './util';
export { util };
I get these warnings because I re-export my classes from index.js as mentioned above. I did not enable loose mode, I'm just using the standard es2015 preset. But hot reload on the components in question sure seems to be working, despite the warning. Has anyone else noticed this?
@altaurog You are right.
Hot reloading is working as expected here but the warning is still showing.
Remove warnings:
@altaurog Same thing happens to me. It seems that this warning is just a warning. The component still got reloaded. So why the warning?
@mitkaaa I tried babel-plugin-add-module-exports but it did not work for me. I guess it only works for export default case?
Same issue here, got the warning but the component still got reloaded !
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.
@Zacqary It is useful for me, thx.
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?
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
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.
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
Thank you nikhilyeole1, worked first try!
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.
Most helpful comment
I too was getting this issue. After reading comments above i fixed it by doing following thing
Useful link -
https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0#.rvrx62s5p