Skip to content

Commit

Permalink
feat(app): introduce modular structure
Browse files Browse the repository at this point in the history
  • Loading branch information
feychenie committed Feb 14, 2019
1 parent 0e9fded commit f3c4a6c
Show file tree
Hide file tree
Showing 22 changed files with 156 additions and 81 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NODE_PATH=src/modules
20 changes: 11 additions & 9 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@ import Theme from "./components/Theme";
import "semantic-ui-css/semantic.min.css";
import "./app.css";
import styles from "./app.module.css";

const mapStateToProps = state => ({
title: state.config.appTitle,
displayClock: state.config.displayClock
});

const ConnectedHeader = connect(mapStateToProps)(AppHeader);

class App extends Component {
render() {
const { title, displayClock } = this.props;
console.log("App render");
return (
<Router>
<Theme.Provider value={{ mainColor: "#333", altColor: "pink" }}>
Expand All @@ -37,7 +45,7 @@ class App extends Component {
<Router> only accepts a single children, so we have to use a Fragment too
*/}
<AppHeader title={title} displayClock={displayClock} />
<ConnectedHeader />
<div className={styles.main}>
<main className={styles.mainInner}>
<Routes />
Expand All @@ -48,11 +56,5 @@ class App extends Component {
);
}
}
const mapStateToProps = state => ({
title: state.appTitle,
displayClock: state.displayClock
});

const ConnectedApp = connect(mapStateToProps)(App);

export default ConnectedApp;
export default App;
4 changes: 2 additions & 2 deletions src/components/AppHeader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const AppHeader = ({ title, displayClock, ...props }) => (
<Menu.Item as={Link} to="/">
{title || "React Class: 1"}
</Menu.Item>
<Menu.Item as={Link} to="/about">
About
<Menu.Item as={Link} to="/config">
Config
</Menu.Item>
<Menu.Item as={Link} to="/hoc">
HOC pattern
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/createReduxStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import actionLogger from "../middlewares/actionLogger";
const middlewares = applyMiddleware(actionLogger);
const devToolsMiddelwares = composeWithDevTools(middlewares);

export default (initialState = {}) =>
export default initialState =>
createStore(reducer, initialState, devToolsMiddelwares);
5 changes: 1 addition & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import createReduxStore from "./helpers/createReduxStore";
// see service workers in any doc about PWA's and create-react-app doc
import * as serviceWorker from "./serviceWorker";

const store = createReduxStore({
appTitle: "Super",
displayClock: true
});
const store = createReduxStore();

ReactDOM.render(
<ReduxProvider store={store}>
Expand Down
File renamed without changes.
46 changes: 46 additions & 0 deletions src/modules/config/pages/ConfigPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from "react";

import { Header } from "semantic-ui-react";
import { connect } from "react-redux";

import { updateTitle, updateClockDisplay } from "../actions";

const TitleInput = connect(
(state, ownProps) => ({ title: state[ownProps.namespace].appTitle }),
dispatch => ({ handleTitleChange: value => dispatch(updateTitle(value)) })
)(({ title, handleTitleChange }) => (
<input value={title} onChange={e => handleTitleChange(e.target.value)} />
));

const DisplayInput = connect(
(state, ownProps) => ({
displayClock: state[ownProps.namespace].displayClock
}),
dispatch => ({
handleClockDisplay: value => dispatch(updateClockDisplay(value)) // dispatch(updateClockDisplay(value))
})
)(({ displayClock, handleClockDisplay }) => (
<input
type="checkbox"
onChange={e => handleClockDisplay(e.target.checked)}
checked={displayClock}
/>
));

const ConfigPage = ({ namespace }) => (
<>
<Header>About this site</Header>
<p>
<TitleInput namespace={namespace} />
</p>
<p>
<label>Display clock ? </label>
<DisplayInput namespace={namespace} />
</p>
</>
);
ConfigPage.defaultProps = {
handleTitleChange: a => a
};

export default ConfigPage;
19 changes: 19 additions & 0 deletions src/modules/config/reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { UPDATE_TITLE, DISPLAY_CLOCK } from "./actions";

const initialConfig = {
appTitle: "Super",
displayClock: true
};

const configReducer = (state = initialConfig, action) => {
switch (action.type) {
case UPDATE_TITLE:
return { ...state, appTitle: action.payload };
case DISPLAY_CLOCK:
return { ...state, displayClock: action.payload };
default:
return state;
}
};

export default configReducer;
19 changes: 19 additions & 0 deletions src/modules/config/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { Route } from "react-router-dom";

import ConfigPage from "./pages/ConfigPage";

const ConfigRoutes = ({ prefix, namespace }) => (
<>
<Route
path={prefix}
render={props => <ConfigPage namespace={namespace} {...props} />}
/>
</>
);

ConfigRoutes.defautProps = {
prefix: "/config"
};

export default ConfigRoutes;
6 changes: 6 additions & 0 deletions src/modules/shows/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const FETCH_SHOWS = "FETCH_SHOWS";

export const fetchShows = () => ({
type: FETCH_SHOWS,
payload: ""
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions src/modules/shows/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import ShowPage from "./ShowPage";
import ShowPages from "./ShowPages";

export { ShowPage, ShowPages };
14 changes: 14 additions & 0 deletions src/modules/shows/reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const initialState = {
shows: []
};

const cases = {};

// cases["actionName"] = (state, action) => state; //

const reducer = (state = initialState, action) => {
if (cases[action.type]) return cases[action.type](state, action);
return state;
};

export default reducer;
19 changes: 19 additions & 0 deletions src/modules/shows/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { Route } from "react-router-dom";

import ShowsPage from "./pages/ShowsPage";
import ShowPage from "./pages/ShowPage";

const ShowsRoutes = ({ prefix, namespace }) => (
<>
<Route path={prefix} component={ShowsPage} />
<Route path={`${prefix}/:id`} component={ShowPage} />
</>
);

ShowsRoutes.defautProps = {
prefix: "/shows",
namespace: "shows"
};

export default ShowsRoutes;
48 changes: 0 additions & 48 deletions src/pages/AboutPage.js

This file was deleted.

19 changes: 8 additions & 11 deletions src/reducer.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { UPDATE_TITLE, DISPLAY_CLOCK } from "./actions";
import { combineReducers } from "redux";

const appReducer = (state = {}, action) => {
switch (action.type) {
case UPDATE_TITLE:
return { ...state, appTitle: action.payload };
case DISPLAY_CLOCK:
return { ...state, displayClock: action.payload };
default:
return state;
}
};
import configReducer from "config/reducer";
import showsReducer from "shows/reducer";

const appReducer = combineReducers({
shows: showsReducer,
config: configReducer
});

export default appReducer;
11 changes: 5 additions & 6 deletions src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React from "react";
import { Route } from "react-router-dom";

import IndexPage from "./pages/IndexPage";
import AboutPage from "./pages/AboutPage";
import HocPage from "./pages/Hoc";
import ShowsPage from "./pages/ShowsPage";
import ShowPage from "./pages/ShowPage";

import ShowsRoutes from "shows/routes";
import ConfigRoutes from "config/routes";

export default () => (
<>
Expand All @@ -14,9 +14,8 @@ export default () => (
Here '/' won't render on '/about' anymore.
*/}
<Route path="/" exact component={IndexPage} />
<Route path="/about" component={AboutPage} />
<Route path="/hoc" component={HocPage} />
<Route path="/shows" component={ShowsPage} />
<Route path="/show/:id" component={ShowPage} />
<ShowsRoutes prefix="/shows" />
<ConfigRoutes prefix="/config" namespace="config" />
</>
);

0 comments on commit f3c4a6c

Please sign in to comment.