Aktualizacja state przy wywoływaniach metod w react

0

Kod, który tu zamieszczam jest częścią kursu Reacta z udemy. Dlaczego po wykonaniu metody addIngredientHandler, a następnie updatePurchaseState state dla ingredients nie działa do konca poprawnie jak metoda updatePurchaseState będzie wyglądać tak jak poniżej? Została wykonana metoda setState w addIngredientHandler to czemu potem najnowszej wartości nie mam w state dla ingredients w metodzie updatePurchaseState?:

updatePurchaseState () {
        const ingredients = {
            ...this.state.ingredients
        };

        const sum = Object.keys( ingredients )
            .map( igKey => {
                return ingredients[igKey];
            } )
            .reduce( ( sum, el ) => {
                return sum + el;
            }, 0 );
        this.setState( { purchasable: sum > 0 } );
    }
import React, { Component } from 'react';

import Aux from '../../hoc/Auxiliary/Auxiliary';
import Burger from '../../components/Burger/Burger';
import BuildControls from '../../components/Burger/BuildControls/BuildControls';
import Modal from '../../components/UI/Modal/Modal';
import OrderSummary from '../../components/Burger/OrderSummary/OrderSummary';

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
    }

    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 updatedCount = oldCount + 1;
        const updatedIngredients = {
            ...this.state.ingredients
        };
        updatedIngredients[type] = updatedCount;
        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 updatedCount = oldCount - 1;
        const updatedIngredients = {
            ...this.state.ingredients
        };
        updatedIngredients[type] = updatedCount;
        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!');
    }

    render () {
        const disabledInfo = {
            ...this.state.ingredients
        };
        for ( let key in disabledInfo ) {
            disabledInfo[key] = disabledInfo[key] <= 0
        }
        // {salad: true, meat: false, ...}
        return (
            <Aux>
                <Modal show={this.state.purchasing} modalClosed={this.purchaseCancelHandler}>
                    <OrderSummary 
                        ingredients={this.state.ingredients}
                        price={this.state.totalPrice}
                        purchaseCancelled={this.purchaseCancelHandler}
                        purchaseContinued={this.purchaseContinueHandler} />
                </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} />
            </Aux>
        );
    }
}

export default BurgerBuilder;
2

setState jest asynchroniczny. Wykona się dopiero później jak zwolnisz główny wątek i React zacznie procesować komunikaty.

0
tsz napisał(a):

setState jest asynchroniczny. Wykona się dopiero później jak zwolnisz główny wątek i React zacznie procesować komunikaty.

a kiedy zwalnia się główny wątek? Jak wszystkie metody zostaną wykonane w danym komponecie?

1
konewka85 napisał(a):
tsz napisał(a):

setState jest asynchroniczny. Wykona się dopiero później jak zwolnisz główny wątek i React zacznie procesować komunikaty.

a kiedy zwalnia się główny wątek? Jak wszystkie metody zostaną wykonane w danym komponecie?

Jak się wykona kod JS od którego się to, że tak powiem, zaczęło.

Silniki JavaScript są z gruntu jednowątkowe. Na przykład jakbyś zrobił coś takiego:

setTimeout(f, 1);
setTimeout(g, 1);

To silnik JS niezwłocznie zacznie wykonywać funkcję f i pomimo, że kolejny timeout powinien się wywołać w tej samej chwili to będzie wisiał dopóki się ona nie wykona. Dopiero jak skończy się wywołanie funkcji f to zacznie wykonywać funkcję g.

1 użytkowników online, w tym zalogowanych: 0, gości: 1