Skip to content

Commit 8708124

Browse files
author
Vivek Chowdhury
committed
added redux store support [Work in progress]
1 parent a6e80ed commit 8708124

File tree

11 files changed

+171
-33
lines changed

11 files changed

+171
-33
lines changed

package-lock.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"prop-types": "^15.7.2",
1111
"react": "^16.13.1",
1212
"react-dom": "^16.13.1",
13+
"react-redux": "^7.2.0",
1314
"react-router-dom": "^5.2.0",
1415
"react-scripts": "3.4.1",
1516
"redux": "^4.0.5",
@@ -42,6 +43,7 @@
4243
"devDependencies": {
4344
"cross-env": "^7.0.2",
4445
"json-server": "^0.16.1",
45-
"npm-run-all": "^4.1.5"
46+
"npm-run-all": "^4.1.5",
47+
"redux-immutable-state-invariant": "^2.1.0"
4648
}
4749
}

src/app/Header/Header.js

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useEffect, useState } from "react";
22
import "./Header.css";
33
import { NavLink, Link } from "react-router-dom";
4+
import { connect } from "react-redux";
45

56
function Header(props) {
67
const [isListening, setIsListening] = useState(false);
@@ -42,16 +43,18 @@ function Header(props) {
4243
Feeds
4344
</NavLink>
4445
</li>
45-
<li className="nav-item">
46-
<NavLink
47-
className={
48-
doChangeBackground ? "nav_link_light" : "nav_link_dark"
49-
}
50-
to="/profile"
51-
>
52-
Profile
53-
</NavLink>
54-
</li>
46+
{props.user.id && (
47+
<li className="nav-item">
48+
<NavLink
49+
className={
50+
doChangeBackground ? "nav_link_light" : "nav_link_dark"
51+
}
52+
to="/profile"
53+
>
54+
Profile
55+
</NavLink>
56+
</li>
57+
)}
5558
</ul>
5659

5760
<ul className="navbar-nav right-options">
@@ -92,4 +95,9 @@ function Header(props) {
9295
);
9396
}
9497

95-
export default Header;
98+
function mapToStateProps(state) {
99+
return {
100+
user: state.user,
101+
};
102+
}
103+
export default connect(mapToStateProps)(Header);

src/app/Login/Login.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import React, { useState } from "react";
1+
import React, { useState, useEffect } from "react";
22
import "./Login.css";
33
import LoginForm from "./LoginForm/LoginForm";
44
import bubbleimage from "./../../assets/placeholders/bubble-image.png";
5-
import * as LoginServices from "./../../api/LoginServices";
5+
// import * as LoginServices from "./../../api/LoginServices";
6+
import { connect } from "react-redux";
7+
import * as validateUser from "./loginActions";
8+
import { bindActionCreators } from "redux";
69

710
function Login(props) {
811
const [user, setUser] = useState({ userId: "", password: "" });
@@ -15,18 +18,31 @@ function Login(props) {
1518
});
1619
};
1720

21+
useEffect(() => {
22+
if (props.user.id !== "") {
23+
props.history.push("/feeds");
24+
}
25+
if (props.user.error !== "") {
26+
updateErrorMessage();
27+
}
28+
}, [props.history, props.user]);
29+
30+
const updateErrorMessage = () => {
31+
setError("Invalid User naem or Password, please try again !");
32+
};
33+
1834
const handleSubmit = (event) => {
1935
event.preventDefault();
20-
console.log(user);
21-
LoginServices.validateUser(user.userId, user.password).then((response) => {
22-
console.log(response);
23-
if (!response.error) {
24-
props.history.push("/feeds");
25-
} else {
26-
setError("Invalid User naem or Password, please try again !");
27-
// TODO: Need to display error message
28-
}
29-
});
36+
// LoginServices.validateUser(user.userId, user.password).then((response) => {
37+
// console.log(response);
38+
// if (!response.error) {
39+
// props.history.push("/feeds");
40+
// } else {
41+
// setError("Invalid User naem or Password, please try again !");
42+
// // TODO: Need to display error message
43+
// }
44+
// });
45+
props.actions.validateUser(user);
3046
};
3147

3248
return (
@@ -48,4 +64,16 @@ function Login(props) {
4864
);
4965
}
5066

51-
export default Login;
67+
function mapStateToProps(state) {
68+
return {
69+
user: state.user,
70+
};
71+
}
72+
73+
function mapDispatchToProps(dispatch) {
74+
return {
75+
actions: bindActionCreators(validateUser, dispatch),
76+
};
77+
}
78+
79+
export default connect(mapStateToProps, mapDispatchToProps)(Login);

src/app/Login/loginActionTypes.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const VALIDATE_USER = "VALIDATE_USER";
2+
export const USER_VALIDATED_SUCCESSFULLY = "USER_VALIDATED_SUCCESSFULLY";
3+
export const USER_VALIDATION_FAILED = "USER_VALIDATION_FAILED";
4+
export const REMEMBER_ME = "REMEMBER_ME";

src/app/Login/loginActions.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as Actions from "./loginActionTypes";
2+
import * as Services from "./../../api/LoginServices";
3+
4+
export function onSuccessfulValidation(response) {
5+
return { type: Actions.USER_VALIDATED_SUCCESSFULLY, response };
6+
}
7+
8+
export function validateUser(user) {
9+
return function (dispatch) {
10+
return Services.validateUser(user.userId, user.password)
11+
.then((response) => {
12+
dispatch(onSuccessfulValidation(response));
13+
})
14+
.catch((error) => {
15+
throw error;
16+
});
17+
};
18+
}

src/app/Login/loginReducer.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import * as Actions from "./loginActionTypes";
2+
3+
const initialUser = {
4+
id: "",
5+
password: "",
6+
error: "",
7+
};
8+
9+
export default function loginReducer(state = initialUser, action) {
10+
// debugger;
11+
switch (action.type) {
12+
case Actions.USER_VALIDATED_SUCCESSFULLY:
13+
return {
14+
...state,
15+
...action.response,
16+
};
17+
default:
18+
return state;
19+
}
20+
}

src/app/TechMarketShell.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import Profile from "./Profile/Profile";
99
import About from "./About/About";
1010
import ContactUs from "./ContactUs/ContactUs";
1111
import Login from "./Login/Login";
12+
import { connect } from "react-redux";
13+
// import { validateUser } from "./Login/loginActions";
1214

1315
function TechMarketShell(props) {
1416
function enforceAuthentication(component, path, user) {
15-
if (!user) {
17+
if (!user.userId && !user.password) {
1618
return <Redirect exact from={path} to="/" />;
1719
}
1820
return <Route exact path={path} component={component} />;
@@ -24,9 +26,9 @@ function TechMarketShell(props) {
2426
<div className="container-fluid contentContainer">
2527
<Switch>
2628
<Route path="/" exact component={Login} />
27-
<Route path="/feeds" component={Feeds} />
28-
{/* <Route path="/profile" component={Profile} /> */}
29-
{enforceAuthentication(Profile, "/profile", {})}
29+
{/* <Route path="/feeds" component={Feeds} /> */}
30+
{enforceAuthentication(Feeds, "/feeds", props.user)}
31+
<Route path="/profile" component={Profile} />
3032
<Route path="/about" component={About} />
3133
<Route path="/contact" component={ContactUs} />
3234
</Switch>
@@ -36,4 +38,9 @@ function TechMarketShell(props) {
3638
);
3739
}
3840

39-
export default TechMarketShell;
41+
function mapStateToProps(state) {
42+
return {
43+
user: state.user,
44+
};
45+
}
46+
export default connect(mapStateToProps)(TechMarketShell);

src/app/configureStore.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createStore, compose, applyMiddleware } from "redux";
2+
import reduxImmutableStateInvariant from "redux-immutable-state-invariant";
3+
import rootReducer from "./rootReducer";
4+
import thunk from "redux-thunk";
5+
6+
export default function configureStore(initialState) {
7+
const composeEnhancer =
8+
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // This will add support to redux devtools
9+
return createStore(
10+
rootReducer,
11+
initialState,
12+
// reduxImmutableStateInvariant: This middleware is used to make sure no one update the state directly.
13+
// thunk: is middle ware used to handle async api handling. it automaitcally inject dispatch in action creator
14+
composeEnhancer(applyMiddleware(thunk, reduxImmutableStateInvariant()))
15+
);
16+
}

src/app/rootReducer.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { combineReducers } from "redux";
2+
import loginReducer from "./Login/loginReducer";
3+
4+
const rootReducer = combineReducers({
5+
user: loginReducer,
6+
});
7+
8+
export default rootReducer;

0 commit comments

Comments
 (0)