Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialDustin Brown
2,433 PointsAnyone else getting an error when including React hot loader in the Webpack config?
I'm getting this error when I include React hot loader in the Webpack config:
Module build failed: Error: React Hot Loader: The Webpack loader is now exported separately. If you use Babel, we recommend that you remove "react-hot-loader" from the "loaders" section of your Webpack configuration altogether, and instead add "react-hot-loader/babel" to the "plugins" section of your .babelrc file. If you prefer not to use Babel, replace "react-hot-loader" or "react-hot" with "react-hot-loader/webpack" in the "loaders" section of your Webpack configuration.
I'm attempting to implement the change it recommends. I'm more just wondering if anyone else is getting this same error.
3 Answers
Dustin Brown
2,433 PointsOkay, so removing react-hot
from the loaders in the Webpack config and then adding react-hot-loader/babel
to the .babelrc
plugins worked. Here's what those two files now look like for me:
webpack.config.js
module.exports = {
//...
module: {
loaders: [
{
test: /\.jsx$/,
exclude: /node_modules/,
loaders: ["babel-loader"]
},
//...
]
}
}
.babelrc
{
"presets": ["react", "es2015"],
"plugins": ["react-hot-loader/babel"]
}
Jonathan Ankiewicz
17,901 PointsERROR in ./components/Scoreboard.js
Module parse failed: /Users/jankiewicz/projects/webpack-build/components/Scoreboard.js Unexpected token (69:9)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (69:9)
at Parser.pp$4.raise (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:2221:15)
at Parser.pp.unexpected (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:603:10)
at Parser.pp$3.parseExprAtom (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1822:12)
at Parser.pp$3.parseExprSubscripts (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1715:21)
at Parser.pp$3.parseMaybeUnary (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1692:19)
at Parser.pp$3.parseExprOps (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1637:21)
at Parser.pp$3.parseMaybeConditional (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1620:21)
at Parser.pp$3.parseMaybeAssign (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1597:21)
at Parser.pp$3.parseParenAndDistinguishExpression (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1861:32)
at Parser.pp$3.parseExprAtom (/Users/jankiewicz/projects/webpack-build/node_modules/webpack/node_modules/acorn/dist/acorn.js:1796:19)
@ ./app.jsx 11:18-52
webpack: bundle is now VALID.
Scoreboard file transfer
import React from 'react';
var PLAYERS = [
{
name: "Jim Hoskins",
score: 1,
id: 1,
},
{
name: "Andrew Chalkley",
score: 23,
id: 2,
},
{
name: "Alena Holligan",
score: 4,
id: 3,
},
];
var nextId = 4;
var Stopwatch = React.createClass({
getInitialState: function(){
return {
running: false,
elapsedTime: 0,
previousTime: 0,
}
},
componentDidMount: function(){
this.interval = setInterval(this.onTick, 100);
},
componentWillUnmount: function(){
clearInterval(this.interval);
},
onTick:function(){
if(this.state.running){
var now = Date.now();
this.setState({
previousTime: now,
elapsedTime: this.state.elapsedTime += (now -= this.state.previousTime),
});
}
},
onStart: function(){
this.setState({
running:true,
previousTime: Date.now(),
});
},
onStop: function(){
this.setState({
running:false,
});
},
onReset: function(){
this.setState({
elapsedTime: 0,
previousTime: Date.now(),
});
},
render: function(){
var seconds = Math.floor(this.state.elapsedTime / 1000);
return(
<div className="stopwatch">
<h2>Stopwatch</h2>
<div className="stopwatch-time">{seconds}</div>
{this.state.running ?
<button onClick={this.onStop}>Stop</button>
:
<button onClick={this.onStart}>Start</button>
}
<button onClick={this.onReset}>Reset</button>
</div>
)
}
});
var AddPlayerForm = React.createClass({
propTypes: {
onAdd: React.PropTypes.func.isRequired,
},
getInitialState: function(){
return{
name: "",
};
},
onNameChange: function(e){
this.setState({name: e.target.value});
},
onSubmit: function(e){
e.preventDefault();
this.props.onAdd(this.state.name);
this.setState({name: ''});
},
render: function(){
return (
<div className="add-player-form">
<form onSubmit={this.onSubmit} onChange={this.onNameChange}>
<input type="text" value={this.state.name}/>
<input type="submit" value="Add Player"/>
</form>
</div>
)
}
});
function Stats(props){
var totalPlayers = props.players.length;
var totalPoints = props.players.reduce(function(total, player){
return total + player.score;
}, 0);
return(
<table className="stats">
<tbody>
<tr>
<td>Players: </td>
<td>{totalPlayers}</td>
</tr>
<tr>
<td>Total Points: </td>
<td>{totalPoints}</td>
</tr>
</tbody>
</table>
)
}
Stats.propTypes = {
players: React.PropTypes.array.isRequired,
};
function Header(props) {
return (
<div className="header">
<Stats players={props.players}/>
<h1>{props.title}</h1>
<Stopwatch />
</div>
);
}
Header.propTypes = {
title: React.PropTypes.string.isRequired,
players: React.PropTypes.array.isRequired,
};
function Counter(props){
return (
<div className="counter">
<button className="counter-action decrement" onClick={function(){props.onChange(-1);}}> - </button>
<div className="counter-score"> {props.score} </div>
<button className="counter-action increment" onClick={function(){props.onChange(+1);}}> + </button>
</div>
);
}
Counter.propTypes = {
score: React.PropTypes.number.isRequired,
onChange: React.PropTypes.func.isRequired,
}
function Player(props) {
return (
<div className="player">
<div className="player-name">
<a className="remove-player" onClick={props.onRemove}>X</a>
{props.name}
</div>
<div className="player-score">
<Counter score={props.score} onChange={props.onScoreChange}/>
</div>
</div>
);
}
Player.propTypes = {
name: React.PropTypes.string.isRequired,
score: React.PropTypes.number.isRequired,
onScoreChange: React.PropTypes.func.isRequired,
onRemove: React.PropTypes.func.isRequired,
};
var Application = React.createClass ({
propTypes: {
title: React.PropTypes.string,
initialPlayers: React.PropTypes.arrayOf(React.PropTypes.shape({
name: React.PropTypes.string.isRequired,
score: React.PropTypes.number.isRequired,
id: React.PropTypes.number.isRequired,
})).isRequired,
},
getDefaultProps: function(){
return {
title: "Scoreboard",
}
},
getInitialState: function(){
return {
players: this.props.initialPlayers,
};
},
onScoreChange: function( index, delta){
console.log(delta + ' ' + index);
this.state.players[index].score += delta;
this.setState(this.state);
},
onPlayerAdd: function(name){
console.log('player added' + name);
this.state.players.push({
name: name,
score: 0,
id: nextId,
});
this.setState(this.state);
nextId += 1;
},
onRemovePlayer: function(index){
this.state.players.splice(index, 1);
this.setState(this.state);
},
render : function(){
return (
<div className="scoreboard">
<Header title={this.props.title} players={this.state.players} />
<div className="players">
{this.state.players.map(function(player, index) {
return (
<Player
onScoreChange={function(delta){this.onScoreChange(index, delta)}.bind(this)}
onRemove={function(){this.onRemovePlayer(index)}.bind(this)}
name={player.name}
score={player.score}
key={player.id} />
);
}.bind(this))}
</div>
<AddPlayerForm onAdd={this.onPlayerAdd} />
</div>
);
}
});
export default Scoreboard;
Nicolas Hampton
44,638 PointsFrom your export statement, I can see you're using webpack to transpile this from es6 to es5, because the export default statement is in es6 format. If you're using the configuration in the best answer above, then it's the name of your file that is the problem. The regular expression in the webpack.config.js above is looking for a file name ending in .jsx, but your scoreboard is named Scoreboard.js. Change it to Scoreboard.jsx, and it should work.
Courtney Drake
Courses Plus Student 5,183 Pointsi'm not getting any errors, however the react-hot-loader is detecting when my css or components change, but it is not actually reloading the app? here's my webpack configuration
module.exports = {
entry: './app.js',
output: {
// path: 'build',
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['react-hot-loader', 'babel-loader']
},
{
test: /\.css$/,
loader: 'style-loader!css-loader'
}
]
}
};
Ricky Johnston
27,445 PointsI was getting this same issue, but then I removed react-hot-loader from my list of loaders, but kept the --hot flag in my npm start function, and it worked a charm.
Nicolas Hampton
44,638 PointsNicolas Hampton
44,638 PointsI noticed that too, and made that correction. React gets modified pretty regularly, so keep an eye out for errors like that and just follow the directions they give.
Brendan Whiting
Front End Web Development Techdegree Graduate 84,738 PointsBrendan Whiting
Front End Web Development Techdegree Graduate 84,738 PointsThanks, this helped me
Älex K
7,809 PointsÄlex K
7,809 PointsThanks, that helped me. But beware, the key inside loaders is called "loader" not "loaders"
Jesus Mendoza
23,289 PointsJesus Mendoza
23,289 PointsYou can also use
{ loaders: ['react-hot-loader/webpack', 'babel'], test: /\.js$/, exclude: /node_modules/ }
inside your loaders instead on the .babelrc file