Skip to main content

10.06 Displaying Spinner While Sending Request

Grab the Spinner

projects.lukehaas.me: CSS Loaders

New Spinner.js

Spinner.js
import React from "react";
import classes from "./Spinner.module.css";

const spinner = () => <div className={classes.Loader}>Loading...</div>;

export default spinner;

New Spinner.module.css

caution

Change all .loaders to .Loaders. And don't forget to add the module keyword to the filename.

Spinner.module.css
.Loader,
.Loader:before,
.Loader:after {
border-radius: 50%;
}
.Loader {
color: #521751;
font-size: 11px;
text-indent: -99999em;
margin: 55px auto;
position: relative;
width: 10em;
height: 10em;
box-shadow: inset 0 0 0 1em;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
}
.Loader:before,
.Loader:after {
position: absolute;
content: "";
}
.Loader:before {
width: 5.2em;
height: 10.2em;
background: #fff;
border-radius: 10.2em 0 0 10.2em;
top: -0.1em;
left: -0.1em;
-webkit-transform-origin: 5.1em 5.1em;
transform-origin: 5.1em 5.1em;
-webkit-animation: load2 2s infinite ease 1.5s;
animation: load2 2s infinite ease 1.5s;
}
.Loader:after {
width: 5.2em;
height: 10.2em;
background: #fff;
border-radius: 0 10.2em 10.2em 0;
top: -0.1em;
left: 4.9em;
-webkit-transform-origin: 0.1em 5.1em;
transform-origin: 0.1em 5.1em;
-webkit-animation: load2 2s infinite ease;
animation: load2 2s infinite ease;
}
@-webkit-keyframes load2 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load2 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}

BurgerBuilder.js

BurgerBuilder.js
import React, { Component, Fragment } from "react";
import axios from "../../axios-orders";
import BuildControls from "../../components/Burger/BuildControls/BuildControls";
import Burger from "../../components/Burger/Burger";
import OrderSummary from "../../components/Burger/OrderSummary/OrderSummary";
import Modal from "../../components/UI/Modal/Modal";
import Spinner from "../../components/UI/Spinner/Spinner";

const INGREDIENT_PRICES = {
salad: 0.5,
cheese: 0.4,
meat: 1.3,
bacon: 0.7,
};

class BurgerBuilder extends Component {
// constructor(props) {
// super(props);
// this.state = {...}
// }
state = {
ingredients: {
salad: 0,
bacon: 0,
cheese: 0,
meat: 0,
},
totalPrice: 4,
purchasable: false,
purchasing: false,
loading: false,
};

updatePurchaseState(ingredients) {
const sum = Object.keys(ingredients)
.map((igKey) => {
return ingredients[igKey];
})
.reduce((sum, el) => {
return sum + el;
}, 0);
this.setState({ purchasable: sum > 0 });
}

addIngredientHandler = (type) => {
const oldCount = this.state.ingredients[type];
const updateCount = oldCount + 1;
const updatedIngredients = {
...this.state.ingredients,
};
updatedIngredients[type] = updateCount;
const priceAddition = INGREDIENT_PRICES[type];
const oldPrice = this.state.totalPrice;
const newPrice = oldPrice + priceAddition;
this.setState({ totalPrice: newPrice, ingredients: updatedIngredients });
this.updatePurchaseState(updatedIngredients);
};

removeIngredientHandler = (type) => {
const oldCount = this.state.ingredients[type];
if (oldCount <= 0) {
return;
}
const updateCount = oldCount - 1;
const updatedIngredients = {
...this.state.ingredients,
};
updatedIngredients[type] = updateCount;
const priceDeduction = INGREDIENT_PRICES[type];
const oldPrice = this.state.totalPrice;
const newPrice = oldPrice - priceDeduction;
this.setState({ totalPrice: newPrice, ingredients: updatedIngredients });
this.updatePurchaseState(updatedIngredients);
};

purchaseHandler = () => {
this.setState({ purchasing: true });
};

purchaseCancelHandler = () => {
this.setState({ purchasing: false });
};

purchaseContinueHandler = () => {
// alert("You continue!");
this.setState({ loading: true });
const order = {
ingredients: this.state.ingredients,
price: this.state.totalPrice,
customer: {
name: "Pash Pa",
address: {
street: "Teststreet 1",
zipCode: "34234",
country: "Russia",
},
email: "test@test.com",
},
deliveryMethod: "fastest",
};
axios
.post("/orders.json", order)
.then((response) => {
this.setState({ loading: false, purchasing: false });
})
.catch((error) => {
this.setState({ loading: false, purchasing: false });
});
};
render() {
const disabledInfo = {
...this.state.ingredients,
};

for (let key in disabledInfo) {
disabledInfo[key] = disabledInfo[key] <= 0;
}

let orderSummary = (
<OrderSummary
ingredients={this.state.ingredients}
purchaseCancelled={this.purchaseCancelHandler}
purchaseContinued={this.purchaseContinueHandler}
price={this.state.totalPrice}
/>
);

if (this.state.loading) {
orderSummary = <Spinner />;
}

return (
<Fragment>
<Modal
show={this.state.purchasing}
modalClosed={this.purchaseCancelHandler}
>
{orderSummary}
</Modal>

<Burger ingredients={this.state.ingredients} />
<BuildControls
ingredientAdded={this.addIngredientHandler}
ingredientRemoved={this.removeIngredientHandler}
disabled={disabledInfo}
purchasable={this.state.purchasable}
ordered={this.purchaseHandler}
price={this.state.totalPrice}
/>
</Fragment>
);
}
}
export default BurgerBuilder;

Modal.js

Modal.js
import React, { Component, Fragment } from "react";
import Backdrop from "../Backdrop/Backdrop";
import classes from "./Modal.module.css";

class Modal extends Component {
shouldComponentUpdate(nextProps, nextState) {
return (
nextProps.show !== this.props.show ||
nextProps.children !== this.props.children
);
}

componentWillUpdate() {
console.log("[Modal] WillUpdate");
}
render() {
return (
<Fragment>
<Backdrop show={this.props.show} clicked={this.props.modalClosed} />
<div
className={classes.Modal}
style={{
transform: this.props.show ? "translateY(0)" : "translateY(-100vh)",
opacity: this.props.show ? "1" : "0",
}}
>
{this.props.children}
</div>
</Fragment>
);
}
}

export default Modal;