Skip to content

Remove react import #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
# react.js shopping cart
# ReactJS shopping cart

example of shopping cart implemented in react.js and redux.js
Example of shopping cart implemented in ReactJS and ReduxJS

for demo [click here](http://krzysu.github.io/reactjs-shopping-cart/)
For demo [click here](http://krzysu.github.io/reactjs-shopping-cart/)

## getting started
## Getting started

install dependencies and start local dev server
install dependencies

```sh
npm install
```

start local dev server

```sh
npm start
```

## details

- build with [create react app](https://github.com/facebookincubator/create-react-app). Check their page for more details.
- this example is using redux.js for application state management, to learn more about it I recommend [this tutorial](https://egghead.io/courses/getting-started-with-redux).
- you can look under the hood directly from your browser using [redux devtools](https://github.com/zalmoxisus/redux-devtools-extension). Install extension for your browser, open demo page (link above) and see how app state changes when you interact with it.
- if you wonder why reducers, actions and selectors are all in one file inside folder called `ducks`, [read more here](https://github.com/erikras/ducks-modular-redux).

## TODO

- add reducers and selectors unit tests

* * *
author: Kris Urbas [@krzysu](https://twitter.com/krzysu)
---

author: Kris Urbas [@krzysu](https://twitter.com/krzysu)
licence: MIT
53 changes: 27 additions & 26 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
import React from 'react';
import Cart from './containers/Cart';
import ProductList from './containers/ProductList';
import Cart from "./containers/Cart";
import ProductList from "./containers/ProductList";

const App = () => {
return (
<div className="container">
<div className="row">
<div className="col-md-12">
<h1>React+Redux Shopping Cart Example</h1>
</div>
</div>
<div className="row">
<div className="col-md-8">
<ProductList />
</div>
<div className="col-md-4">
<Cart />
</div>
</div>

<footer>
<small>
made by <a href="https://twitter.com/krzysu">Kris Urbas</a>, source code available on <a href="https://github.com/krzysu/reactjs-shopping-cart">github</a>
</small>
</footer>
return (
<div className="container">
<div className="row">
<div className="col-md-12">
<h1>React+Redux Shopping Cart Example</h1>
</div>
</div>
<div className="row">
<div className="col-md-8">
<ProductList />
</div>
);
}
<div className="col-md-4">
<Cart />
</div>
</div>

<footer>
<small>
made by <a href="https://twitter.com/krzysu">Kris Urbas</a>, source
code available on{" "}
<a href="https://github.com/krzysu/reactjs-shopping-cart">github</a>
</small>
</footer>
</div>
);
};

export default App;
63 changes: 34 additions & 29 deletions src/components/Cart/Cart.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
import React from 'react';
import PropTypes from 'prop-types';
import CartItem from './CartItem';
import PropTypes from "prop-types";
import CartItem from "./CartItem";

const Cart = ({ items, total, currency, removeFromCart }) => {
return (
<div>
<h3>Shopping Cart</h3>
return (
<div>
<h3>Shopping Cart</h3>

<div className="cart">
<div className="panel panel-default">
<div className="panel-body">
{items.length > 0 && (
<div className="cart__body">
{items.map(item => (
<CartItem key={item.id} {...item} onClick={() => removeFromCart(item.id)} />
))}
</div>
)}
{items.length === 0 && (
<div className="alert alert-info">Cart is empty</div>
)}
<div className="cart__total">Total: {total} {currency}</div>
</div>
</div>
<div className="cart">
<div className="panel panel-default">
<div className="panel-body">
{items.length > 0 && (
<div className="cart__body">
{items.map((item) => (
<CartItem
key={item.id}
{...item}
onClick={() => removeFromCart(item.id)}
/>
))}
</div>
)}
{items.length === 0 && (
<div className="alert alert-info">Cart is empty</div>
)}
<div className="cart__total">
Total: {total} {currency}
</div>
</div>
</div>
);
}
</div>
</div>
);
};

Cart.propTypes = {
items: PropTypes.array,
total: PropTypes.number,
currency: PropTypes.string,
removeFromCart: PropTypes.func.isRequired
}
items: PropTypes.array,
total: PropTypes.number,
currency: PropTypes.string,
removeFromCart: PropTypes.func.isRequired,
};

export default Cart;
37 changes: 20 additions & 17 deletions src/components/Cart/CartItem.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import React from 'react';
import PropTypes from 'prop-types';
import PropTypes from "prop-types";

const CartItem = ({ name, price, currency, onClick }) => {
return (
<div className="cart-item">
<div>
<button className="btn btn-danger btn-xs" onClick={onClick}>X</button>
<span className="cart-item__name">{name}</span>
</div>
<div className="cart-item__price">{price} {currency}</div>
</div>
);
}
return (
<div className="cart-item">
<div>
<button className="btn btn-danger btn-xs" onClick={onClick}>
X
</button>
<span className="cart-item__name">{name}</span>
</div>
<div className="cart-item__price">
{price} {currency}
</div>
</div>
);
};

CartItem.propTypes = {
name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
currency: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired
}
name: PropTypes.string.isRequired,
price: PropTypes.number.isRequired,
currency: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
};

export default CartItem;
78 changes: 40 additions & 38 deletions src/components/Product/Product.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,51 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Component } from "react";
import PropTypes from "prop-types";

class Product extends Component {
handleClick = () => {
const { id, addToCart, removeFromCart, isInCart } = this.props;
handleClick = () => {
const { id, addToCart, removeFromCart, isInCart } = this.props;

if (isInCart) {
removeFromCart(id);
} else {
addToCart(id);
}
if (isInCart) {
removeFromCart(id);
} else {
addToCart(id);
}
};

render() {
const { name, price, currency, image, isInCart } = this.props;
render() {
const { name, price, currency, image, isInCart } = this.props;

return (
<div className="product thumbnail">
<img src={image} alt="product" />
<div className="caption">
<h3>{name}</h3>
<div className="product__price">{price} {currency}</div>
<div className="product__button-wrap">
<button
className={isInCart ? 'btn btn-danger' : 'btn btn-primary'}
onClick={this.handleClick}
>
{isInCart ? 'Remove' : 'Add to cart'}
</button>
</div>
</div>
</div>
);
}
return (
<div className="product thumbnail">
<img src={image} alt="product" />
<div className="caption">
<h3>{name}</h3>
<div className="product__price">
{price} {currency}
</div>
<div className="product__button-wrap">
<button
className={isInCart ? "btn btn-danger" : "btn btn-primary"}
onClick={this.handleClick}
>
{isInCart ? "Remove" : "Add to cart"}
</button>
</div>
</div>
</div>
);
}
}

Product.propTypes = {
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
price: PropTypes.number,
currency: PropTypes.string,
image: PropTypes.string,
isInCart: PropTypes.bool.isRequired,
addToCart: PropTypes.func.isRequired,
removeFromCart: PropTypes.func.isRequired,
}
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
price: PropTypes.number,
currency: PropTypes.string,
image: PropTypes.string,
isInCart: PropTypes.bool.isRequired,
addToCart: PropTypes.func.isRequired,
removeFromCart: PropTypes.func.isRequired,
};

export default Product;
35 changes: 17 additions & 18 deletions src/components/ProductList/ProductList.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import Product from '../../containers/Product';
import PropTypes from "prop-types";
import Product from "../../containers/Product";

const ProductList = ({ products }) => {
return (
<div>
<h3>Products</h3>
<ul className="product-list">
{products.map(product => (
<li key={product.id} className="product-list__item">
<Product {...product} />
</li>
))}
</ul>
</div>
);
}
return (
<div>
<h3>Products</h3>
<ul className="product-list">
{products.map((product) => (
<li key={product.id} className="product-list__item">
<Product {...product} />
</li>
))}
</ul>
</div>
);
};

ProductList.propTypes = {
products: PropTypes.array,
}
products: PropTypes.array,
};

export default ProductList;
39 changes: 19 additions & 20 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { combineReducers, createStore } from 'redux';
import cartReducer from './ducks/cart';
import productsReducer from './ducks/products';
import App from './App';
import productsData from './data/products';
import 'bootstrap/dist/css/bootstrap.css';
import { render } from "react-dom";
import { Provider } from "react-redux";
import { combineReducers, createStore } from "redux";
import cartReducer from "./ducks/cart";
import productsReducer from "./ducks/products";
import App from "./App";
import productsData from "./data/products";
import "bootstrap/dist/css/bootstrap.css";

const rootReducer = combineReducers({
cart: cartReducer,
products: productsReducer
cart: cartReducer,
products: productsReducer,
});

let store = createStore(
rootReducer,
{
products: productsData // initial store values
},
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // for debugging
rootReducer,
{
products: productsData, // initial store values
},
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() // for debugging
);

render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);