React-Redux using HOC

yarn add redux redux-logger react-redux
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './redux/store';import './index.css';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
import { combineReducers } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import userReducer from './user/user.reducer';
import cartReducer from './cart/cart.reducer';
import directoryReducer from './directory/directory.reducer';
import shopReducer from './shop/shop.reducer';
const persistConfig = {
key: 'root',
storage,
whitelist: ['cart']
};
const rootReducer = combineReducers({
user: userReducer,
cart: cartReducer,
directory: directoryReducer,
shop: shopReducer
});
export default persistReducer(persistConfig, rootReducer);
import CartActionTypes from './cart.types';
import { addItemToCart, removeItemFromCart } from './cart.utils';
const INITIAL_STATE = {
hidden: true,
cartItems: []
};
const cartReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case CartActionTypes.TOGGLE_CART_HIDDEN:
return {
...state,
hidden: !state.hidden
};
case CartActionTypes.ADD_ITEM:
return {
...state,
cartItems: addItemToCart(state.cartItems, action.payload)
};
case CartActionTypes.REMOVE_ITEM:
return {
...state,
cartItems: removeItemFromCart(state.cartItems, action.payload)
};
case CartActionTypes.CLEAR_ITEM_FROM_CART:
return {
...state,
cartItems: state.cartItems.filter(
cartItem => cartItem.id !== action.payload.id
)
};
default:
return state;
}
};
export default cartReducer;
import { createStore, applyMiddleware } from 'redux';
import { persistStore } from 'redux-persist';
import logger from 'redux-logger';
import rootReducer from './root-reducer';const middlewares = [];if (process.env.NODE_ENV === 'development') {
middlewares.push(logger);
}
export const store = createStore(rootReducer, applyMiddleware(...middlewares));export const persistor = persistStore(store);export default { store, persistStore };
import CartActionTypes from './cart.types';export const toggleCartHidden = () => ({
type: CartActionTypes.TOGGLE_CART_HIDDEN
});
export const addItem = item => ({
type: CartActionTypes.ADD_ITEM,
payload: item
});
export const removeItem = item => ({
type: CartActionTypes.REMOVE_ITEM,
payload: item
});
export const clearItemFromCart = item => ({
type: CartActionTypes.CLEAR_ITEM_FROM_CART,
payload: item
});
const CartActionTypes = {
TOGGLE_CART_HIDDEN: "TOGGLE_CART_HIDDEN",
ADD_ITEM: "ADD_ITEM",
REMOVE_ITEM: "REMOVE_ITEM",
CLEAR_ITEM_FROM_CART: "CLEAR_ITEM_FROM_CART",
CLEAR_CART: 'CLEAR_CART'
}
export default CartActionTypes
import React from 'react';
import { connect } from 'react-redux';
import CollectionItem from '../../components/collection-item/collection-item.component';
import { selectCollection } from '../../redux/shop/shop.selectors';import {
CollectionPageContainer,
CollectionTitle,
CollectionItemsContainer
} from './collection.styles';
const CollectionPage = ({ collection }) => {
const { title, items } = collection;
return (
<CollectionPageContainer>
<CollectionTitle>{title}</CollectionTitle>
<CollectionItemsContainer>
{items.map(item => (
<CollectionItem key={item.id} item={item} />
))}
</CollectionItemsContainer>
</CollectionPageContainer>
);
};
const mapStateToProps = (state, ownProps) => ({
collection: selectCollection(ownProps.match.params.collectionId)(state)
});
export default connect(mapStateToProps)(CollectionPage);
import React from 'react'import {connect} from 'react-redux'


import CustomButton from '../custom-button/custom-button.component'
import {addItem} from '../../redux/cart/cart.actions.js'
import './collection-item.styles.scss'const CollectionItem = ({ item, addItem }) => {
const { name, price, imageUrl} = item
return(
<div className='collection-item'>
<div
className='image'
style={{
backgroundImage: `url(${imageUrl})`
}}

/>

<div className='collection-footer'>
<span className='name'> {name}</span>
<span className='price'> {price}</span>

</div>
<CustomButton onClick={() => addItem(item) } inverted > Add to cart </CustomButton>
</div>
)}
const mapDispatchToProps = dispatch => ({
addItem: item => dispatch(addItem(item))
})
export default connect(null, mapDispatchToProps)(CollectionItem)
export const addItemToCart = (cartItems, cartItemToAdd) => {
const existingCartItem = cartItems.find(cartItem => cartItem.id === cartItemToAdd.id)
if (existingCartItem) {
return cartItems.map(cartItem =>
cartItem.id === cartItemToAdd.id ?
{
...cartItem,
quantity: cartItem.quantity + 1
} :
cartItem
);
}
return [...cartItems, {...cartItemToAdd, quantity: 1}]}export const removeItemFromCart = (cartItems, cartItemToRemove) => {
const existingCartItem = cartItems.find(cartItem => cartItem.id === cartItemToRemove.id)
if (existingCartItem.quantity === 1) {
return cartItems.filter(cartItem => cartItem.id !== cartItemToRemove.id)
}
return cartItems.map(cartItem =>
cartItem.id === cartItemToRemove.id
? {...cartItem, quantity: cartItem.quantity - 1}
: cartItem
)
}
import { createSelector } from 'reselect'const selectCart = state => state.cartexport const selectCartItems = createSelector(
[selectCart], (cart) => cart.cartItems
)
export const selectCartHidden = createSelector(
[selectCart],
cart => cart.hidden
)
export const selectCartItemsCount = createSelector(
[selectCartItems], cartItems => cartItems.reduce(
(accumulatedQuantity, cartItem) =>
accumulatedQuantity + cartItem.quantity, 0)
)
export const selectCartTotal = createSelector(
[selectCartItems],
cartItems => cartItems.reduce(
(accumulatedQuantity, cartItem) =>
accumulatedQuantity + cartItem.price * cartItem.quantity, 0)
import React from 'react'
import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect'
import { selectCartItems, selectCartTotal} from '../../redux/cart/cart.selectors'
import CheckoutITem from '../../components/checkout-item/checkout-item.component'
import StripeCheckoutButton from '../../components/stripe-button/stripe-button.component'
import './checkout.style.scss'
const CheckoutPage = ({cartItems, total}) => (
<div className='checkout-page'>
<div className='checkout-header'>
<div className='heaser-block'>
<span> Product</span>
</div>
<div className='heaser-block'>
<span>Description</span>
</div>
<div className='heaser-block'>
<span>Quantity</span>
</div>
<div className='heaser-block'>
<span>Price</span>
</div>
<div className='heaser-block'>
<span>Remove</span>
</div>
</div>
<div>
{cartItems.map(cartItem => (
<CheckoutITem key={cartItem.id}cartItem={cartItem}/>
))}
</div>
<div className='total'><span> ${total} </span> </div>
<div className='test-warning'>
*Please use the following test credit card for payments*
<br />
4242 4242 4242 4242 - Exp:01/22 - CVV: 123

</div>
<StripeCheckoutButton price={total} />
</div>
)
const mapStateToProps = createStructuredSelector({
cartItems: selectCartItems,
total: selectCartTotal
})
export default connect(mapStateToProps)(CheckoutPage)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Avitosh Totaram

Avitosh Totaram

Problem solver with experience in Software, and Mechanical engineering. Interested in web-dev, machine learning, artificial intelligence, and new technologies.