diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 6ac330f04..6a8660e87 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -11,7 +11,8 @@ import makeClassName from 'classnames'; import log from 'loglevel'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import styles from './styles.module.scss'; import { ApiState, actions as apiActions } from '../../reducers/api'; import { diff --git a/src/components/FileTree/index.tsx b/src/components/FileTree/index.tsx index e409a3dfe..1b4052edd 100644 --- a/src/components/FileTree/index.tsx +++ b/src/components/FileTree/index.tsx @@ -9,7 +9,8 @@ import FileTreeNode, { PublicProps as FileTreeNodeProps, } from '../FileTreeNode'; import Loading from '../Loading'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import { FileTree, TreeNode, diff --git a/src/components/LinterProvider/index.tsx b/src/components/LinterProvider/index.tsx index 6038c4a91..9e37c4d9f 100644 --- a/src/components/LinterProvider/index.tsx +++ b/src/components/LinterProvider/index.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; import { connect } from 'react-redux'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import { LinterMessageMap, LinterMessagesByPath, diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index c3e74eaa5..83efd2835 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -5,7 +5,8 @@ import { Link } from 'react-router-dom'; import { gettext } from '../../utils'; import LoginButton from '../LoginButton'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import { User, selectCurrentUser, requestLogOut } from '../../reducers/users'; import styles from './styles.module.scss'; diff --git a/src/components/VersionChooser/index.tsx b/src/components/VersionChooser/index.tsx index 8551f1bba..6f941989c 100644 --- a/src/components/VersionChooser/index.tsx +++ b/src/components/VersionChooser/index.tsx @@ -4,7 +4,8 @@ import { connect } from 'react-redux'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import Loading from '../Loading'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import VersionSelect from '../VersionSelect'; import { VersionsMap, fetchVersionsList } from '../../reducers/versions'; import { gettext } from '../../utils'; diff --git a/src/configureStore.tsx b/src/configureStore.tsx index a3532562d..4bac60357 100644 --- a/src/configureStore.tsx +++ b/src/configureStore.tsx @@ -4,7 +4,6 @@ import { Middleware, Store, applyMiddleware, - combineReducers, createStore, } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; @@ -15,21 +14,7 @@ import thunk, { ThunkMiddleware, } from 'redux-thunk'; -import api, { ApiState } from './reducers/api'; -import errors, { ErrorsState } from './reducers/errors'; -import fileTree, { FileTreeState } from './reducers/fileTree'; -import linter, { LinterState } from './reducers/linter'; -import users, { UsersState } from './reducers/users'; -import versions, { VersionsState } from './reducers/versions'; - -export type ApplicationState = { - api: ApiState; - errors: ErrorsState; - fileTree: FileTreeState; - linter: LinterState; - users: UsersState; - versions: VersionsState; -}; +import createRootReducer, { ApplicationState } from './reducers'; export type ThunkActionCreator = ThunkAction< Promise, @@ -48,37 +33,37 @@ export type ConnectedReduxProps = { dispatch: ThunkDispatch; }; -const createRootReducer = () => { - return combineReducers({ - api, - errors, - fileTree, - linter, - users, - versions, - }); -}; - const configureStore = ( preloadedState?: ApplicationState, ): Store => { const allMiddleware: Middleware[] = [ thunk as ThunkMiddleware, ]; - let addDevTools = false; + const isDevelopment = process.env.NODE_ENV === 'development'; - if (process.env.NODE_ENV === 'development') { + if (isDevelopment) { allMiddleware.push(createLogger()); - addDevTools = true; } let middleware = applyMiddleware(...allMiddleware); - if (addDevTools) { + if (isDevelopment) { const composeEnhancers = composeWithDevTools({}); middleware = composeEnhancers(middleware); } - return createStore(createRootReducer(), preloadedState, middleware); + const store = createStore(createRootReducer(), preloadedState, middleware); + + if (isDevelopment) { + /* istanbul ignore next */ + if (module.hot) { + /* istanbul ignore next */ + module.hot.accept('./reducers', () => { + store.replaceReducer(createRootReducer()); + }); + } + } + + return store; }; export default configureStore; diff --git a/src/index.tsx b/src/index.tsx index dba827a56..da434346f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -21,11 +21,25 @@ if (authToken === process.env.REACT_APP_AUTH_TOKEN_PLACEHOLDER) { ); } -ReactDOM.render( - - - - - , - rootElement, -); +const render = (AppComponent: typeof App) => { + ReactDOM.render( + + + + + , + rootElement, + ); +}; + +render(App); + +/* istanbul ignore next */ +if (module.hot) { + /* istanbul ignore next */ + module.hot.accept('./components/App', () => { + // eslint-disable-next-line global-require + const NextApp = require('./components/App').default; + render(NextApp); + }); +} diff --git a/src/pages/Browse/index.tsx b/src/pages/Browse/index.tsx index 960f2b30c..96890a408 100644 --- a/src/pages/Browse/index.tsx +++ b/src/pages/Browse/index.tsx @@ -4,7 +4,8 @@ import { connect } from 'react-redux'; import { Col, Row } from 'react-bootstrap'; import log from 'loglevel'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import { ApiState } from '../../reducers/api'; import FileTree from '../../components/FileTree'; import { diff --git a/src/pages/Compare/index.tsx b/src/pages/Compare/index.tsx index 3ccd4bda2..658bf5cea 100644 --- a/src/pages/Compare/index.tsx +++ b/src/pages/Compare/index.tsx @@ -3,7 +3,8 @@ import { Col, Row } from 'react-bootstrap'; import { RouteComponentProps } from 'react-router-dom'; import { connect } from 'react-redux'; -import { ApplicationState, ConnectedReduxProps } from '../../configureStore'; +import { ApplicationState } from '../../reducers'; +import { ConnectedReduxProps } from '../../configureStore'; import FileTree from '../../components/FileTree'; import DiffView from '../../components/DiffView'; import Loading from '../../components/Loading'; diff --git a/src/reducers/index.tsx b/src/reducers/index.tsx new file mode 100644 index 000000000..752076b34 --- /dev/null +++ b/src/reducers/index.tsx @@ -0,0 +1,30 @@ +import { combineReducers } from 'redux'; + +import api, { ApiState } from './api'; +import errors, { ErrorsState } from './errors'; +import fileTree, { FileTreeState } from './fileTree'; +import linter, { LinterState } from './linter'; +import users, { UsersState } from './users'; +import versions, { VersionsState } from './versions'; + +export type ApplicationState = { + api: ApiState; + errors: ErrorsState; + fileTree: FileTreeState; + linter: LinterState; + users: UsersState; + versions: VersionsState; +}; + +const createRootReducer = () => { + return combineReducers({ + api, + errors, + fileTree, + linter, + users, + versions, + }); +}; + +export default createRootReducer; diff --git a/src/test-helpers.tsx b/src/test-helpers.tsx index 3aa3391e8..ee03fde43 100644 --- a/src/test-helpers.tsx +++ b/src/test-helpers.tsx @@ -4,10 +4,8 @@ import { ShallowWrapper, shallow } from 'enzyme'; import { Store } from 'redux'; import log from 'loglevel'; -import configureStore, { - ApplicationState, - ThunkActionCreator, -} from './configureStore'; +import configureStore, { ThunkActionCreator } from './configureStore'; +import { ApplicationState } from './reducers'; import { ExternalLinterResult, ExternalLinterMessage,