Added redux structure that remebers state

This commit is contained in:
2018-04-16 17:10:06 +02:00
parent 57cbb68a6d
commit a7cd381e96
18 changed files with 166 additions and 66 deletions

View File

@@ -79,6 +79,7 @@ module.exports = function(proxy, allowedHost) {
// See https://github.com/facebookincubator/create-react-app/issues/387.
disableDotRule: true,
},
historyApiFallback: true,
public: allowedHost,
proxy,
before(app) {

View File

@@ -7272,6 +7272,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
"integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw=="
},
"lodash-es": {
"version": "4.17.8",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.8.tgz",
"integrity": "sha512-I9mjAxengFAleSThFhhAhvba6fsO0hunb9/0sQ6qQihSZsJRBofv2rYH58WXaOb/O++eUmYpCLywSQ22GfU+sA=="
},
"lodash._reinterpolate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
@@ -10089,6 +10094,19 @@
"prop-types": "15.6.1"
}
},
"react-redux": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
"integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==",
"requires": {
"hoist-non-react-statics": "2.5.0",
"invariant": "2.2.4",
"lodash": "4.17.5",
"lodash-es": "4.17.8",
"loose-envify": "1.3.1",
"prop-types": "15.6.1"
}
},
"react-router": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz",
@@ -10257,6 +10275,17 @@
}
}
},
"redux": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
"integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
"requires": {
"lodash": "4.17.5",
"lodash-es": "4.17.8",
"loose-envify": "1.3.1",
"symbol-observable": "1.2.0"
}
},
"regenerate": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz",
@@ -11513,6 +11542,11 @@
"serviceworker-cache-polyfill": "4.0.0"
}
},
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
},
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",

View File

@@ -40,8 +40,10 @@
"react": "^16.3.1",
"react-dev-utils": "^5.0.1",
"react-dom": "^16.3.1",
"react-redux": "^5.0.7",
"react-router-dom": "^4.2.2",
"react-test-renderer": "^16.3.1",
"redux": "^3.7.2",
"resolve": "1.6.0",
"sass-loader": "^6.0.7",
"style-loader": "0.19.0",

View File

@@ -0,0 +1,6 @@
export const INIT_PAGE = 'INIT_PAGE'
export const initPage = titles => ({
type: INIT_PAGE,
titles
})

View File

@@ -1,12 +1,20 @@
import React from 'react';
import {MemoryRouter as Router} from 'react-router-dom'
import Dashboard from './index';
import {mount} from 'enzyme'
import renderer from 'react-test-renderer';
test('Dummy renders correctly', () => {
const component = renderer.create(
<Router><Dashboard/></Router>,
);
const props = {
title: 'Dashboard',
}
// // const component = renderer.create(
// <Router><Dashboard props ={...props}/></Router>,
// );
const component = mount((<Router><Dashboard {...props} /></Router>))
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

View File

@@ -1,9 +1,16 @@
import React from 'react';
import { connect } from 'react-redux'
import styles from './styles.scss';
import Header from '../Header/index'
const Dashboard = (props) => {
return <div className={styles.colored}><Header/>Dashboard</div>;
return <div className={styles.colored}><Header />Title {props.title}</div>;
};
export default Dashboard;
const mapStateToProps = (state) => {
return {
title: state.pageInitialised.titles.title,
}
}
export default connect(mapStateToProps)(Dashboard);

View File

@@ -1,10 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Dummy renders correctly 1`] = `
<div
className={undefined}
>
Hello,
Hamo
</div>
`;

View File

@@ -1,12 +0,0 @@
import React from 'react';
import Dummy from './index';
import renderer from 'react-test-renderer';
test('Dummy renders correctly', () => {
const component = renderer.create(
<Dummy name="Hamo"/>,
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});

View File

@@ -1,8 +0,0 @@
import React from 'react';
import styles from './styles.scss';
const Dummy = (props) => {
return <div className={styles.colored}>Hello, {props.name}</div>;
};
export default Dummy;

View File

@@ -1,3 +0,0 @@
.colored {
color: blueviolet;
}

View File

@@ -1,6 +1,6 @@
.Header {
padding-top : 12px;
padding-bottom : 12px;
padding-top : 6px;
padding-bottom : 6px;
display: flex;
justify-content: space-between;
align-items:center;

View File

@@ -1,9 +1,16 @@
import React from 'react';
import {connect} from 'react-redux'
import styles from './styles.scss';
import Header from '../Header/index'
const Inbox = (props) => {
return <div className={styles.colored}><Header/>Inbox</div>;
const Inbox = (props) => {
return <div className={styles.colored}><Header/>Title {props.title}</div>;
};
export default Inbox;
const mapStateToProps = (state) => {
return {
title: state.pageInitialised.titles.title,
}
}
export default connect(mapStateToProps)(Inbox);

View File

@@ -1,9 +1,16 @@
import React from 'react';
import { connect } from 'react-redux'
import styles from './styles.scss';
import Header from '../Header/index'
const MyTask = (props) => {
return <div className={styles.colored}><Header/>My Task</div>;
return <div className={styles.colored}><Header />Title {props.title}</div>;
};
export default MyTask;
const mapStateToProps = (state) => {
return {
title: state.pageInitialised.titles.title,
}
}
export default connect(mapStateToProps)(MyTask);

View File

@@ -0,0 +1,53 @@
import React, { Component } from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import App from '../index'
import Inbox from '../Inbox/index';
import MyTask from '../Mytask/index';
import Dashboard from '../Dashboard/index';
import { initPage } from '../../../actions/index'
class Root extends Component {
render() {
return (
<Provider store={this.props.store}>
<Router>
<div>
<Route path='/' exact component={App} />
<Route path="/mytask" exact component={mountComponentWithPathAction(MyTask, this.props)} />
<Route path="/inbox" exact component={mountComponentWithPathAction(Inbox, this.props)} />
<Route path="/dashboard" exact component={mountComponentWithPathAction(Dashboard, this.props)} />
</div>
</Router>
</Provider>
);
}
}
/**
* Pass this function to `react-router-dom` Route component property
* In orderd to triger redux action that is related to te Route path
* If such action exists
*
* @param {} WrappedComponent a React component to render
* @param {*} props a an object containing redux `store` to dispach initPage action with route path name
* @returns A new HIGHT ORDER React component from WrappedComponent after redux action is dispatched
*/
let mountComponentWithPathAction = function (WrappedComponent, props) {
return class extends Component {
componentWillMount() {
props.store.dispatch(initPage({ pathName: this.props.location.pathname }))
}
render() {
return <WrappedComponent {...this.props} />
}
}
}
export default Root

View File

@@ -1,15 +1,10 @@
import React, { Component } from 'react';
import styles from './styles.scss';
import Header from './Header';
class App extends Component {
render() {
return (
<div className={styles.App}>
<header className={styles["App-header"]}>
<h1 className={styles["App-title"]}><Header name="Header"/> </h1>
</header>
</div>
<Header />
);
}
}

View File

@@ -1,23 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom'
import { createStore } from 'redux'
import './index.css';
import App from './components/App';
import registerServiceWorker from './registerServiceWorker';
import Inbox from './components/App/Inbox/index';
import MyTask from './components/App/Mytask/index';
import Dashboard from './components/App/Dashboard/index';
import Dummy from './components/App/Dummy/index';
import subtaskIo from './reducers/index'
import Root from './components/App/Root/index';
const store = createStore(subtaskIo)
ReactDOM.render(
<Router>
<div>
<Route exact path='/' component={App} />
<Route exact path="/mytask" component={MyTask} />
<Route exact path="/inbox" component={Inbox} />
<Route exact path="/dashboard" component={Dashboard} />
</div>
</Router>
,
<Root store={store}/>,
document.getElementById('root'));
registerServiceWorker();

View File

@@ -0,0 +1,7 @@
import { combineReducers } from 'redux'
import pageInitialised from './router'
const subtaskIo = combineReducers({
pageInitialised,
})
export default subtaskIo

View File

@@ -0,0 +1,14 @@
const pageInitialised = (state = {
titles: { title: 'Default title' },
}, action) => {
switch (action.type) {
case 'INIT_PAGE':
return {
...state,
titles: { title: action.titles.pathName }
}
default:
return state
}
}
export default pageInitialised