Skip to content

Commit

Permalink
Redux Thunk
Browse files Browse the repository at this point in the history
  • Loading branch information
navin-moorthy committed Aug 22, 2019
1 parent 5660d40 commit 2e0fdfe
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 30 deletions.
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -14,6 +14,7 @@
"redux": "4.0.4", "redux": "4.0.4",
"redux-logger": "3.0.6", "redux-logger": "3.0.6",
"redux-persist": "5.10.0", "redux-persist": "5.10.0",
"redux-thunk": "^2.3.0",
"reselect": "4.0.0", "reselect": "4.0.0",
"styled-components": "^4.3.2" "styled-components": "^4.3.2"
}, },
Expand Down
45 changes: 20 additions & 25 deletions src/pages/shop/shop.component.jsx
@@ -1,13 +1,10 @@
import React from "react"; import React from "react";
import { Route } from "react-router-dom"; import { Route } from "react-router-dom";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";


import { updateCollections } from "../../redux/shop/shop.actions"; import { fetchCollectionStartAsync } from "../../redux/shop/shop.actions";

import { selectIsCollectionFetching } from "../../redux/shop/shop.selectors";
import {
firestore,
convertCollectionsSnapshotToMap
} from "../../firebase/firebase.utils";


import CollectionPage from "../collection/collection.component"; import CollectionPage from "../collection/collection.component";
import WithSpinner from "../../components/with-spinner/with-spinner.component"; import WithSpinner from "../../components/with-spinner/with-spinner.component";
Expand All @@ -17,51 +14,49 @@ const CollectionPageWithSpinner = WithSpinner(CollectionPage);
const CollectionsOverviewWithSpinner = WithSpinner(CollectionsOverview); const CollectionsOverviewWithSpinner = WithSpinner(CollectionsOverview);


class ShopPage extends React.Component { class ShopPage extends React.Component {
state = {
loading: true
};

componentDidMount() { componentDidMount() {
const { updateCollections } = this.props; const { fetchCollectionStartAsync } = this.props;
const collectionRef = firestore.collection("collections"); fetchCollectionStartAsync();

collectionRef.get().then(snapshot => {
const collectionsMap = convertCollectionsSnapshotToMap(snapshot);
updateCollections(collectionsMap);
this.setState({ loading: false });
});
} }


render() { render() {
const { match } = this.props; const { match, isCollectionFetching } = this.props;
const { loading } = this.state;
return ( return (
<div className="shop-page"> <div className="shop-page">
<Route <Route
exact exact
path={`${match.path}`} path={`${match.path}`}
render={props => ( render={props => (
<CollectionsOverviewWithSpinner isLoading={loading} {...props} /> <CollectionsOverviewWithSpinner
isLoading={isCollectionFetching}
{...props}
/>
)} )}
/> />
<Route <Route
exact exact
path={`${match.path}/:collectionId`} path={`${match.path}/:collectionId`}
render={props => ( render={props => (
<CollectionPageWithSpinner isLoading={loading} {...props} /> <CollectionPageWithSpinner
isLoading={isCollectionFetching}
{...props}
/>
)} )}
/> />
</div> </div>
); );
} }
} }


const mapStateToProps = createStructuredSelector({
isCollectionFetching: selectIsCollectionFetching
});

const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
updateCollections: collectionsMap => fetchCollectionStartAsync: () => dispatch(fetchCollectionStartAsync())
dispatch(updateCollections(collectionsMap))
}); });


export default connect( export default connect(
null, mapStateToProps,
mapDispatchToProps mapDispatchToProps
)(ShopPage); )(ShopPage);
34 changes: 32 additions & 2 deletions src/redux/shop/shop.actions.js
@@ -1,6 +1,36 @@
import { ShopActionTypes } from "./shop.types"; import { ShopActionTypes } from "./shop.types";


export const updateCollections = collectionsMap => ({ import {
type: ShopActionTypes.UPDATE_COLLECTIONS, firestore,
convertCollectionsSnapshotToMap
} from "../../firebase/firebase.utils";

export const fetchCollectionStart = () => ({
type: ShopActionTypes.FETCH_COLLECTIONS_START
});

export const fetchCollectionSuccess = collectionsMap => ({
type: ShopActionTypes.FETCH_COLLECTIONS_SUCCESS,
payload: collectionsMap payload: collectionsMap
}); });

export const fetchCollectionFailure = errorMessage => ({
type: ShopActionTypes.FETCH_COLLECTIONS_FAILURE,
payload: errorMessage
});

export const fetchCollectionStartAsync = () => {
return dispatch => {
const collectionRef = firestore.collection("collections");

dispatch(fetchCollectionStart());

collectionRef
.get()
.then(snapshot => {
const collectionsMap = convertCollectionsSnapshotToMap(snapshot);
dispatch(fetchCollectionSuccess(collectionsMap));
})
.catch(error => dispatch(fetchCollectionFailure(error.message)));
};
};
24 changes: 23 additions & 1 deletion src/redux/shop/shop.reducer.js
@@ -1,11 +1,33 @@
import { ShopActionTypes } from "./shop.types"; import { ShopActionTypes } from "./shop.types";


const INITIAL_DATA = { const INITIAL_DATA = {
collections: null collections: null,
isFetching: false,
errorMessage: undefined
}; };


const shopReducer = (state = INITIAL_DATA, action) => { const shopReducer = (state = INITIAL_DATA, action) => {
switch (action.type) { switch (action.type) {
case ShopActionTypes.FETCH_COLLECTIONS_START:
return {
...state,
isFetching: true
};

case ShopActionTypes.FETCH_COLLECTIONS_SUCCESS:
return {
...state,
isFetching: false,
collections: action.payload
};

case ShopActionTypes.FETCH_COLLECTIONS_FAILURE:
return {
...state,
isFetching: false,
errorMessage: action.payload
};

case ShopActionTypes.UPDATE_COLLECTIONS: case ShopActionTypes.UPDATE_COLLECTIONS:
return { return {
...state, ...state,
Expand Down
5 changes: 5 additions & 0 deletions src/redux/shop/shop.selectors.js
Expand Up @@ -18,3 +18,8 @@ export const selectCollection = collectionUrlParam =>
[selectCollections], [selectCollections],
collections => (collections ? collections[collectionUrlParam] : null) collections => (collections ? collections[collectionUrlParam] : null)
); );

export const selectIsCollectionFetching = createSelector(
[selectShop],
shop => shop.isFetching
);
4 changes: 3 additions & 1 deletion src/redux/shop/shop.types.js
@@ -1,3 +1,5 @@
export const ShopActionTypes = { export const ShopActionTypes = {
UPDATE_COLLECTIONS: "UPDATE_COLLECTIONS" FETCH_COLLECTIONS_START: "FETCH_COLLECTIONS_START",
FETCH_COLLECTIONS_SUCCESS: "FETCH_COLLECTIONS_SUCCESS",
FETCH_COLLECTIONS_FAILURE: "FETCH_COLLECTIONS_FAILURE"
}; };
3 changes: 2 additions & 1 deletion src/redux/store.js
@@ -1,10 +1,11 @@
import { createStore, applyMiddleware } from "redux"; import { createStore, applyMiddleware } from "redux";
import { persistStore } from "redux-persist"; import { persistStore } from "redux-persist";
import logger from "redux-logger"; import logger from "redux-logger";
import thunk from "redux-thunk";


import rootReducer from "./root-reducer"; import rootReducer from "./root-reducer";


const middlewares = []; const middlewares = [thunk];


if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
middlewares.push(logger); middlewares.push(logger);
Expand Down

0 comments on commit 2e0fdfe

Please sign in to comment.