React Hot loader 3 with webpack-dev - javascript

I'm trying to use hot-react-loader in my project.
So I changed some files to work with this but I get an error when I edit a component.
Warning: React.createElement: type should not be null, undefined,
boolean, or number. It should be a string (for DOM elements) or a
ReactClass (for composite components).
[HMR] Cannot apply update. Need to do a full reload!
what am I doing wrong?
webpack.config.dev.js
var webpack = require('webpack');
var path = require('path');
// Questo il plugin di webpack che mi genera il file index.html in dist
var HtmlwebpackPlugin = require('html-webpack-plugin');
const PATHS = {
app: path.join(__dirname, 'app/index'),
build: path.join(__dirname, 'dist')
};
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3500',
'webpack/hot/only-dev-server',
'react-hot-loader/patch',
PATHS.app
],
output: {
path: PATHS.build,
filename: 'js/bundle.js'
},
// Questo serve a non specificare le estensioni
resolve: {
extensions: ['', '.js']
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
},
{ test: /\.(png|jpg)$/, loader: "file?limit=1000&name=images/[hash].[ext]" },
{ test: /\.scss$/, loaders: [ 'style','css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]' ] }
]
},
// Porta utilizzata da webpack-dev-server
devServer: {
port: 3500
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlwebpackPlugin({
title: 'React Starter Kit',
hash: true,
inject: false,
appMountId: 'app',
template: 'jade!./app/assets/index.jade'
})
]
};
server.js
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config.dev');
new WebpackDevServer(webpack(config), {
hot: true,
historyApiFallback: true,
stats: {
colors: true
}
}).listen(3500, 'localhost', function (err) {
if (err) {
console.log(err);
}
console.log('Listening at localhost:3500');
});
index.js
import ReactDOM from 'react-dom';
import React from 'react';
import App from './app';
import { AppContainer } from 'react-hot-loader';
const root = document.getElementById('app');
ReactDOM.render(
<AppContainer>
<App />
</AppContainer>
, root);
if (module.hot) {
module.hot.accept('./app', () => {
const App = require('./app');
ReactDOM.render(
<AppContainer>
<App />
</AppContainer>
, root);
});
}
app.js
import React from 'react';
import { Router, browserHistory } from 'react-router';
import routes from './routes/routes';
const App = () => (
<Router history={browserHistory} routes={routes} />
);
export default App;

You have to modify the prototype chain of the Router component itself to force render the new stuff.
// Router
import { Router, browserHistory } from 'react-router'
if (process.env.NODE_ENV === 'production') {
// ...
} else {
// the hacky workaround
Router.prototype.componentWillReceiveProps = function (nextProps) {
let components = [];
function grabComponents(routes) {
routes.forEach((route) => {
if (route.component) {
components.push(route.component)
}
if (route.indexRoute && route.indexRoute.component) {
components.push(route.indexRoute.component)
}
if (route.childRoutes) {
grabComponents(route.childRoutes)
}
})
}
grabComponents(nextProps.routes)
components.forEach(React.createElement) // force patching
}
}
The code you see here is an adaptation of https://github.com/gaearon/react-hot-boilerplate/pull/61#issuecomment-211504531

Related

React-Router subroutes not displaying

It seems that when webpack builds the file the output can only see the maincard div and none of the contents therein. I'm not sure what's missing as when this is run as npm react-scripts start it works fine. I'm not sure what i'm missing from webpack for this to render correctly. I'm trying to load this into an S3 bucket so it has to be packed with the webpack.
import React from 'react';
import { connect } from 'react-redux';
import { Route, withRouter } from 'react-router-dom';
import { fetchUserList } from "../actions/UserActions";
import { fetchSkillList } from "../actions/SkillActions";
import WelcomeCard from "./WelcomeCard";
import UserSearchCard from "./UserSearchCard";
import AddUserCard from './AddUserCard';
import '../styles/MainCard.css';
class MainCard extends React.Component {
componentDidMount() {
this.props.fetchUserList();
this.props.fetchSkillList();
}
render() {
return (
<div className="main_card">
<Route exact path='/' component={WelcomeCard}/>
<Route path='/list' component={UserSearchCard}/>
<Route path='/new' component={AddUserCard}/>
</div>
);
}
}
const mapDispatchToProps = dispatch => {
return {
fetchUserList: () => dispatch(fetchUserList()),
fetchSkillList: () => dispatch(fetchSkillList())
}
};
export default withRouter( connect(undefined, mapDispatchToProps)(MainCard) );
Webpack Config:
let path = require('path');
let webpack = require('webpack');
const publicPath = '/dist/build/';
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
//Content
entry: './src/index.js',
mode: 'development',
// A SourceMap without column-mappings ignoring loaded Source Maps.
devtool: 'cheap-module-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
}),
//simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you, supply your own template using lodash templates or use your own loader.
new HtmlWebpackPlugin({
title: 'Talent Identification Manager'
}),
//Auto replacement of page when i save some file, even css
new webpack.HotModuleReplacementPlugin(),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
output: {
path: path.join(__dirname, publicPath),
filename: 'main.bundle-0.0.1.js',
publicPath: "/",
sourceMapFilename: 'main.map',
},
devServer: {
port: 3000,
host: 'localhost',
//Be possible go back pressing the "back" button at chrome
historyApiFallback: true,
noInfo: false,
stats: 'minimal',
publicPath: publicPath,
contentBase: path.join(__dirname, publicPath),
//hotmodulereplacementeplugin
hot: true
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules(?!\/webpack-dev-server)/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-2'],
plugins: ['syntax-decorators']
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
}
]
}
}
React Router doesn't know that you want to treat /talentidbucket as the base of your site, so you have explicitly tell it so by passing the base path as the basename prop of the BrowserRouter component in production.
class App extends React.Component {
render() {
return (
<BrowserRouter basename="/talentidbucket"> {/* ... */} </BrowserRouter>
);
}
}

Cannot GET /currentSite on refresh react

I have a problem. I cant refresh my react components/page without getting "Cannot GET /currentPage". I've browsed you for some time now and found a couple of links that could be the solution of my issue:
https://github.com/jintoppy/react-training/blob/master/basic/node_modules/react-router/docs/guides/Histories.md#browserhistory
HashHistory of BrowserHistory. Internet said I should use BrowserHistory for production - but that hashHistory is easier. They are both so effing complicated. I cant for my life figure out how to implement it to my current code.
This is my app.js file:
/*global $:true*/
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import './scss/app.scss';
// Component imports
import Home from './components/home';
import Archive from './archive';
// Image import
import loadImg from './images/tits.gif';
class App extends Component {
// Function for anchorlinks
hashLinkScroll() {
const { hash } = window.location;
if (hash !== '') {
// Push onto callback queue so it runs after the DOM is updated, this is required when navigating from a different page so that the element is rendered on the page before trying to getElementById
setTimeout(() => {
const id = hash.replace('#', '');
const element = document.getElementById(id);
if (element) element.scrollIntoView();
}, 100);
}
}
// 1. Render site-loader gif
// 2. React Router component wraps all of the routes we are going to define - Archive and Home. Each route will be identified in a <Route> component. The <Route> component will take two properties: path and component. When a path matches the path given to the <Route> component, it will return the component specified.
render() {
return (
<div>
<div className="loaderSmall">
<img className="loadingImg" src={loadImg} width="400"/>
</div>
<Router history={browserHistory} onUpdate={this.hashLinkScroll}>
<Route path={'/archive'} component={Archive} />
<Route path={'*'} component={Home} />
</Router>
</div>
);
};
// When Component has rendered, window.addEventListener adds event "load" and calls handleLoad function
componentDidMount() {
window.addEventListener('load', this.handleLoad);
}
// Fade out site-loader
handleLoad() {
$(".loaderSmall").delay(500).fadeOut("slow");
}
};
ReactDOM.render (
<App/>,
document.getElementById('app')
)
// Hot Module Replacement API (injecting code)
if (module.hot) {
module.hot.accept();
}
export default App;
..this is my menu component that renders when I am on "/archive" component:
import React, { Component } from 'react';
import { Link } from 'react-router';
//Menu component renders menu Link
class Menu extends Component {
render() {
return (
<header>
<nav>
<ul>
<li><Link to={'/#top'}>Home</Link></li>
<li><Link to={'/#about'}>About</Link></li>
<li><Link to={'/archive'}>Archive</Link></li>
<li className="contactMobile">Contact</li>
<li className="contactWeb"><Link to={'/#contact'}>Contact</Link></li>
</ul>
</nav>
</header>
);
}
}
export default Menu;
..and this is my other menu that renders when i am on root where i want scrollable hashlinks:
import React, { Component } from 'react';
import { Link } from 'react-router';
import Scrollchor from 'react-scrollchor';
//Menu component renders menu Link
class MenuB extends Component {
render() {
return (
<header>
<nav>
<ul>
<li><Scrollchor to="#top" animate={{offset: 20, duration: 800}}>Home</Scrollchor></li>
<li><Scrollchor to="#about" animate={{offset: 0, duration: 800}}>About</Scrollchor></li>
<li><Link to={'/archive'}>Archive</Link></li>
<li className="contactMobile">Contact</li>
<li className="contactWeb"><Scrollchor to="#contact" animate={{offset: 20, duration: 800}}>Contact</Scrollchor></li>
</ul>
</nav>
</header>
);
}
}
export default MenuB;
my webpack.config.js file:
// DEVELOPMENT
const webpack = require('webpack');
const path = require('path');
const entry = [
'webpack-dev-server/client?http://localhost:8080', // bundle the client for webpack-dev-server and connect to the provided endpoint
'webpack/hot/only-dev-server', // bundle the client for hot reloading only- means to only hot reload for successful updates
'./app.js'
]
const output = {
path: path.join(__dirname, 'dist'),
publicPath: '/dist',
filename: 'bundle.min.js'
}
const plugins = [
new webpack.HotModuleReplacementPlugin(), // enable HMR globally
new webpack.NamedModulesPlugin() // prints more readable module names in the browser console on HMR updates
]
const config = {
context: path.join(__dirname, 'src'),
entry: entry,
output: output,
devtool: "inline-source-map",
module: {
rules: [
{
// test: /\.(js|jsx)$/,
// exclude: /node_modules/,
// include: path.join(__dirname, 'src'),
// use: {
// loader: "eslint-loader",
// options: {
// failOnWarning: false,
// failOnError: false
// }
// }
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
use: {
loader: "babel-loader"
}
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: { limit: 10000, name: './images/[name].[ext]' }
}]
},
{
test: /\.(sass|scss)$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
},
performance: {
maxAssetSize: 400000000,
maxEntrypointSize: 400000000,
hints: 'warning'
},
plugins: plugins,
externals: {
jquery: 'jQuery'
}
}
module.exports = config
And my webpack.config.prod.js file:
// PRODUCTION
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const entry = {
app: path.join(process.cwd(), 'src/app.js')
}
const output = {
path: path.join(__dirname, 'dist'),
filename: 'bundle.min.js',
}
const plugins = [
new webpack.DefinePlugin({
// 'process.env.NODE_ENV': JSON.stringify('production')
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
mangle: false,
compress: {
warnings: false
}
}),
new ExtractTextPlugin('bundle.css'), // creation of HTML files to serve your webpack bundles
new HtmlWebpackPlugin({
template: 'index-template.html'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'bundle',
filename: '[name].common.js'
})
]
const config = {
context: path.join(__dirname, 'src'),
entry: entry,
output: output,
devtool: "source-map",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
use: "babel-loader"
},
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: { limit: 10000, name: './images/[name].[ext]' } // Convert images < 10k to base64 strings (all in images folder)
}]
},
{
test: /\.(sass|scss)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: (loader) => [ require('autoprefixer')() ]
}
},
'sass-loader',
]
})
}
]
},
plugins: plugins,
externals: {
jquery: 'jQuery'
}
}
module.exports = config;
..I know that there are much better ways to do this than to have two menu components that renders on different pages, but I just did this solution for now .. Problem is that I don't understans how to convert this to HashHistory of BrowserHistory without loosing my logic. Any tips/input would be so goddammit appreciated, been sitting with this for weeks now <3
Cannot GET /currentPage ?
For browserHistory on page refresh ,/currentPage is requested on server side.
At the backend, your server dont defined this path (requested resource).
You need to implement it to fixed Cannot GET issue for page refresh.
Assuming nodejs
app.use(express.static(__dirname));
//will serve index.html for every page refresh.
app.use('*',(req,resp)=>{
res.sendFile(path.resolve(__dirname+'/index.html'))
})
app.listen(someport)
This will load index.html page for every page refresh.
Once index.html is loaded with required JS & react router,
the router will trigger the route and corresponding component is getting rendered.
#Panther solved this. To be able to refresh page in my dev environment, I had to add:
historyApiFallback: {
disableDotRule: true
}
to my webpack dev.server file:
var WebpackDevServer = require('webpack-dev-server');
var webpack = require('webpack');
// requiring my webpack configuration
var config = require('./webpack.config.js');
var path = require('path');
var compiler = webpack(config);
// then spinning up a new dev server with some settings
var server = new WebpackDevServer(compiler, {
hot: true,
filename: config.output.filename,
publicPath: config.output.publicPath,
proxy: {
"/getMail": 'http://localhost:80/magdan/php/mailer.php',
"/getProducts": 'http://localhost:80/magdan/php/products.php'
},
stats: {
colors: true
},
historyApiFallback: {
disableDotRule: true
}
});
// its gonna listen to port 8080
server.listen(8080, 'localhost', function() {
console.log("Starting server on http://localhost:8080");
});

Issue with Webpack using React

Sorry if this is a duplicate question. I can't seem to solve this or find an answer. I have a basic Webpack setup i'm working with in conjunction with React and Django. Basically I'm getting compilation error's when using webpack.
These two webpack files aren't loading properly, both below, and neither is this App module (I think it's the provider component from redux).
I think it may be something to do with a driver - or something very simple that I've missed. I would really appreciate the help as I've been trying to fix this for a long time now haha!
Thanks!!!
webpack.config.local.config.js
var path = require("path")
var webpack = require('webpack')
var BundleTracker = require('webpack-bundle-tracker')
var ip = 'localhost'
var config = require('./webpack.base.config.js')
config.devtool = "#eval-source-map"
config.entry = {
App1: [
'webpack-dev-server/client?http://' + ip + ':3000',
'webpack/hot/only-dev-server',
'./reactjs/App1',
],
}
config.output.publicPath = 'http://' + ip + ':3000' + '/assets/bundles/'
config.plugins = config.plugins.concat([
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new BundleTracker({filename: './webpack-stats-local.json'}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development'),
'BASE_API_URL': JSON.stringify('https://'+ ip +':3000/api/v1/'),
}}),
])
config.module.loaders.push(
{ test: /\.js?$/, exclude: /node_modules/, loaders: ['react-hot', 'babel'] }
)
module.exports = config
webpack.base.config.js
var path = require("path")
var webpack = require('webpack')
module.exports = {
context: __dirname,
entry: {
// Add as many entry points as you have container-react-components here
App1: './reactjs/App1',
vendors: ['react']
},
output: {
path: path.resolve('./djreact/static/bundles/local/'),
filename: "[name]-[hash].js"
},
externals: [
], // add all vendor libs
plugins: [
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'),
], // add all common plugins here
module: {
loaders: [
// js
{
test: /\.js$/,
exclude: /node_modules/,
loaders: ['babel'],
presets: ['es2015', 'react'],
},
// PNG
{
test : /\.(png|jpg|svg)$/,
include : path.join(__dirname, 'img'),
loader : 'url-loader?limit=30000&name=images/[name].[ext]'
},
{
test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
},
// CSS
{
test: /\.scss$/,
include: path.join(__dirname, 'client'),
loader: 'style-loader!css-loader!sass-loader'
}
] // add all common loaders here
},
resolve: {
modulesDirectories: ['node_modules', 'bower_components'],
extensions: ['', '.js', '.jsx']
},
}
The App that is having some errors
App1.js
import React from "react"
import { render } from "react-dom"
import {
createStore,
compose,
applyMiddleware,
combineReducers,
} from "redux"
import { Router, Route, hashHistory, IndexRoute } from 'react-router'
import { Provider } from "react-redux"
import thunk from "redux-thunk"
import * as reducers from "./reducers"
import App1Container from "./containers/App1Container"
let finalCreateStore = compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore)
let reducer = combineReducers(reducers)
let store = finalCreateStore(reducer)
class App1 extends React.Component {
render() {
return (
<Provider store={store}>
<Router history = {hashHistory}>
<Route path="/" component={Layout}>
<IndexRoute component = {App1Container}/>
</Route>
</Router>
<App1Container />
</Provider>
)
}
}
render(<App1/>, document.getElementById('App1'))
So here are the errors.
From webpack.local.config.js
From webpack.base.config.js
webpack.base.config.js => jsx syntax error, I think that is wrong babel settings
Can you share your .babelrc?
Usually, this file is as follows.
{
"presets": ["es2015","react"]
}

Trying to make React Hot, Express and Webpack work together

I'm a backend guy that has decided to learn some frontend, but it seems that I'm pretty far from learning since I can't even configure the environment.
My goal is to setup Webpack with Babel 6, React, react-hot and HotModuleReplacementPlugin. I also want the app to have express.js server. So here're my configs:
server.js:
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('./webpack.config')
var app = new (require('express'))()
var port = 4000
var compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
app.use(webpackHotMiddleware(compiler))
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/index.html')
})
app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> http://localhost:%s/", port)
}
})
webpack.config.js
var webpack = require('webpack');
var path = require('path');
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:4000',
'webpack/hot/only-dev-server',
'./src/index'
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
preLoaders: [
{ test: /\.jsx?$/, loader: 'eslint', exclude: /node_modules/ }
],
loaders: [
{
test: /\.jsx?$/,
loaders: ['react-hot', 'babel?presets[]=es2015,presets[]=stage-0,presets[]=react,plugins[]=transform-runtime'],
include: path.join(__dirname, 'src')
}
]
}
}
public/index.html
<html>
<head>
<title>React setup</title>
</head>
<body>
<div id='root'>
</div>
<script src='bundle.js'></script>
</body>
</html>
src/App.js
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
<h1>Hello, world!</h1>
);
}
}
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
And here's what I've got in my console (the error is looped):

React / Webpack component not showing, what's wrong

This is all new and no doubt I'm doing something stupid, but I have a component that I can't get to show up.
Here's my webpack.config.js
var path = require('path');
var webpack = require('webpack');
var bootstratp = require('react-bootstrap');
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./src/index',
],
output: {
path: path.join(__dirname, 'dist'),
//path: 'build',
filename: 'bundle.js',
publicPath: '/static/'
},
resolve:{
extensions:['','.js','.jsx']
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'src')
}]
}
};
Here's the index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
Here's the App.js
import React, { Component } from 'react';
import {Button} from 'react-bootstrap';
import TestBox from './components/test';
var path = require('path');
export default class App extends Component {
render() {
return (
<div>
<h1>aaa</h1>
<TestBox/>
</div>
);
}
}
Finally here's the component that isn't showing up:
export default
TestBox = React.createClass({
render:function(){
return <div>ABCD</div>
}
});
You don't need to put an equal sign in front of the export default:
try this, similar to how you have it in App.js:
let TestBox = React.createClass({
render:function(){
return <div> ABCD </div>
}
});
export default TextBox

Categories