Skip to main content

17.06 Fetching Ingredients Asynchronously

BurgerBuider.js

src\containers\BurgerBuilder\BurgerBuilder.js
import React, { Component, Fragment } from "react";
import { connect } from "react-redux";
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";
import withErrorHandler from "../../hoc/withErrorHandler/withErrorHandler";
import * as burgerBuilderActions from "../../store/actions/index";

class BurgerBuilder extends Component {
// constructor(props) {
// super(props);
// this.state = {...}
// }
state = {
purchasable: false,
purchasing: false,
};

componentDidMount() {
console.log(this.props);
}

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

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

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

purchaseContinueHandler = () => {
this.props.history.push("/checkout");
};
render() {
const disabledInfo = {
...this.props.ings,
};

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

let burger = this.state.error ? (
<p>Ingredients can't be loaded!</p>
) : (
<Spinner />
);

if (this.props.ings) {
burger = (
<Fragment>
<Burger ingredients={this.props.ings} />
<BuildControls
ingredientAdded={this.props.onIgredientAdded}
ingredientRemoved={this.props.onIgredientRemoved}
disabled={disabledInfo}
purchasable={this.updatePurchaseState(this.props.ings)}
ordered={this.purchaseHandler}
price={this.props.price}
/>
</Fragment>
);

orderSummary = (
<OrderSummary
ingredients={this.props.ings}
purchaseCancelled={this.purchaseCancelHandler}
purchaseContinued={this.purchaseContinueHandler}
price={this.props.price}
/>
);
}

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

const mapStateToProps = (state) => {
return {
ings: state.ingredients,
price: state.totalPrice,
};
};

const mapDispatchToProps = (dispatch) => {
return {
onIgredientAdded: (ingName) =>
dispatch(burgerBuilderActions.addIngredient(ingName)),
onIgredientRemoved: (ingName) =>
dispatch(burgerBuilderActions.removeIngredient(ingName)),
};
};

export default connect(
mapStateToProps,
mapDispatchToProps
)(withErrorHandler(BurgerBuilder, axios));

actionTypes.js

src\store\actions\actionTypes.js
export const ADD_INGREDIENT = "ADD_INGREDIENT";
export const REMOVE_INGREDIENT = "REMOVE_INGREDIENT";
export const SET_INGREDIENTS = "SET_INGREDIENTS";
export const FETCH_INGREDIENTS_FAILD = "FETCH_INGREDIENTS_FAILD";

actions/burgerBulder.js

src\store\actions\burgerBuilder.js
import axios from "../../axios-orders";
import * as actionTypes from "./actionTypes";

export const addIngredient = (name) => {
return {
type: actionTypes.ADD_INGREDIENT,
ingredientName: name,
};
};

export const removeIngredient = (name) => {
return {
type: actionTypes.REMOVE_INGREDIENT,
ingredientName: name,
};
};

export const setIngredients = (ingredients) => {
return {
type: actionTypes.SET_INGREDIENTS,
ingredients: ingredients,
};
};

export const fetchIngredientsFaild = () => {
return {
type: actionTypes.FETCH_INGREDIENTS_FAILD,
};
};

export const initIngredients = () => {
return (dispatch) => {
axios
.get(
"https://react-burger-bf7e8-default-rtdb.europe-west1.firebasedatabase.app/ingregients.json"
)
.then((response) => {
dispatch(setIngredients(response.data));
})
.catch((error) => {
dispatch(fetchIngredientsFaild());
});
};
};

reducers/burgerBuilder.js

src\store\reducers\burgerBuilder.js
import * as actionTypes from "../actions/actionTypes";

const initialState = {
ingredients: null,
totalPrice: 4,
error: false,
};

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

const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.ADD_INGREDIENT:
return {
...state,
ingredients: {
...state.ingredients,
[action.ingredientName]: state.ingredients[action.ingredientName] + 1,
},
totalPrice: state.totalPrice + INGREDIENT_PRICES[action.ingredientName],
};
case actionTypes.REMOVE_INGREDIENT:
return {
...state,
ingredients: {
...state.ingredients,
[action.ingredientName]: state.ingredients[action.ingredientName] - 1,
},
totalPrice: state.totalPrice - INGREDIENT_PRICES[action.ingredientName],
};
default:
return state;
}
};

export default reducer;