Fail to get hot module reloading to work

This commit is contained in:
Drew DeVault 2017-08-24 21:46:55 -04:00
parent 409238ba58
commit b6fd35c5f5
7 changed files with 89 additions and 13 deletions

View File

@ -45,7 +45,10 @@
"node-sass": "^4.5.3", "node-sass": "^4.5.3",
"preact": "^8.2.4", "preact": "^8.2.4",
"preact-compat": "^3.17.0", "preact-compat": "^3.17.0",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-fontawesome": "^1.6.1", "react-fontawesome": "^1.6.1",
"react-hot-loader": "^3.0.0-beta.7",
"react-router-dom": "^4.2.0", "react-router-dom": "^4.2.0",
"react-router-redux": "^5.0.0-alpha.6", "react-router-redux": "^5.0.0-alpha.6",
"react-transition-group": "^2.2.0", "react-transition-group": "^2.2.0",

View File

@ -1,8 +1,9 @@
import "babel-polyfill"; import "babel-polyfill";
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux'; import { ConnectedRouter } from 'react-router-redux';
import 'preact/devtools';
import store, { history } from './store'; import store, { history } from './store';
import scss from '../scss/main.scss'; import scss from '../scss/main.scss';
@ -17,16 +18,21 @@ ws_init(() => {
store.dispatch(filter_subscribe('server')); store.dispatch(filter_subscribe('server'));
}); });
render( const render = App => ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<ConnectedRouter history={history}> <ConnectedRouter history={history}>
<div> <div>
<Nav /> <Nav />
<div className="container"> <div className="container">
<Main /> <App />
</div> </div>
</div> </div>
</ConnectedRouter> </ConnectedRouter>
</Provider>, </Provider>,
document.getElementById('root') document.getElementById('root'));
);
render(Main);
if (module.hot) {
module.hot.accept('./ui/main', () => render(Main));
}

View File

@ -16,7 +16,7 @@ export default function ws_send(type, body, callback = null) {
...body ...body
}; };
const msg = JSON.stringify(obj); const msg = JSON.stringify(obj);
console.log("->", obj); console.log("->", type, obj);
ws.send(msg); ws.send(msg);
return _serial; return _serial;
} }
@ -28,7 +28,7 @@ const handlers = {
function ws_recv(e) { function ws_recv(e) {
const msg = JSON.parse(e.data); const msg = JSON.parse(e.data);
console.log("<-", msg); console.log("<-", msg.type, msg);
const cb = transactions[msg.serial]; const cb = transactions[msg.serial];
cb && cb(msg); cb && cb(msg);
const handler = handlers[msg.type]; const handler = handlers[msg.type];

View File

@ -18,6 +18,14 @@ const store = createStore(
_compose(applyMiddleware(thunk, routerMiddleware(history))), _compose(applyMiddleware(thunk, routerMiddleware(history))),
); );
if (module.hot) {
// Enable webpack hot module replacement for reducers
module.hot.accept(
'./reducers',
() => store.replaceReducer(reducers)
);
}
export const dispatch = action => store.dispatch(action); export const dispatch = action => store.dispatch(action);
export const getState = () => store.getState(); export const getState = () => store.getState();

0
src/ui/index.js Normal file
View File

View File

@ -1,15 +1,71 @@
import React from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { activeTorrents } from '../torrent_state';
import {
Button,
ButtonGroup,
ButtonDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem
} from 'reactstrap';
// TODO: use component lifecycle functions here to invoke // TODO: use component lifecycle functions here to invoke
// torrent_state.updateSubscriptions // torrent_state.updateSubscriptions
function torrent_details(props) { function Torrent(props) {
return ( return (
<div> <div>
<h3>Torrent details</h3> <h3>{props.torrent.name}</h3>
</div> </div>
); );
} }
export default connect(state => ({ router: state.router }))(torrent_details); class TorrentDetails extends Component {
constructor() {
super();
this.state = {
removeDropdown: false
};
}
renderHeader(active) {
return (
<div>
<h3>{active.length} torrents</h3>
<ButtonGroup>
<Button color="info">Pause all</Button>{' '}
<Button color="success">Resume all</Button>{' '}
<ButtonDropdown
isOpen={this.state.removeDropdown}
toggle={() => this.setState({ removeDropdown: !this.state.removeDropdown })}
>
<DropdownToggle color="danger" caret>
Remove
</DropdownToggle>
<DropdownMenu>
<DropdownItem>Remove torrent</DropdownItem>
<DropdownItem>Delete files</DropdownItem>
</DropdownMenu>
</ButtonDropdown>
</ButtonGroup>
</div>
);
}
render() {
const active = activeTorrents();
const { torrents } = this.props;
return (
<div>
{active.length > 1 ? this.renderHeader(active) : null}
{active.map(id => <Torrent torrent={torrents[id]} />)}
</div>
);
}
}
export default connect(state => ({
router: state.router,
torrents: state.torrents
}))(TorrentDetails);

View File

@ -9,6 +9,7 @@ const defines = {
module.exports = { module.exports = {
devtool: "source-map", devtool: "source-map",
entry: [ entry: [
'react-hot-loader/patch',
"webpack-hot-middleware/client", "webpack-hot-middleware/client",
"font-awesome-sass-loader!./font-awesome.config.js", "font-awesome-sass-loader!./font-awesome.config.js",
"./src/index.js" "./src/index.js"
@ -51,12 +52,14 @@ module.exports = {
}, },
plugins:[ plugins:[
new webpack.HotModuleReplacementPlugin(), new webpack.HotModuleReplacementPlugin(),
new webpack.EnvironmentPlugin(defines) new webpack.EnvironmentPlugin(defines),
new webpack.NamedModulesPlugin(),
], ],
resolve: { resolve: {
alias: { alias: {
"react": "preact-compat", "react": "preact-compat",
"react-dom": "preact-compat" "react-dom": "preact-compat",
"preact-compat": "preact-compat/dist/preact-compat"
} }
} }
}; };