React Project: Adding Redux to Synchronous Data passing

Redux 用于存放ingredients和prices(全局调用的state)

index.js
Provider需要包裹所有的东西;

import React, { createContext } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import {BrowserRouter} from 'react-router-dom';

import {Provider} from 'react-redux';
import {createStore} from 'redux';
import reducer from './store/reducer';

const store =createStore(reducer);

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

reducer.js
先不用异步操作请求http,初始化ingredients先;
设置函数改变ingredients;

为改变price,需要加入每个ingredients的价格列表,在add和remove时进行加减;

import * as actionTypes from './actions';

const initialState ={          //定义价格
    ingredients: {
        salad:0,
        bacon:0,
        cheese:0,
        meat:0
    },
    totalPrice: 3.7
};


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_INGREDIENTS:
            return {
                ...state,
                ingredients:{
                    ...state.ingredients,
                    [action.ingredientName]:state.ingredients[action.ingredientName]+1  
                    //【】可存放代码
                },
                totalPrice:state.totalPrice+INGREDIENT_PRICES[action.ingredientName]
            };

        case actionTypes.REMOVE_INGREDIENTS:
            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;

export default reducer;

BurgerBuilder.js
去掉与ingredients和price有关的state内容;
使用connect将witherror等包裹;
传入需要用到的redux props state和redux props dispatch;

将this.state.ingredients全部改为this.props.ings
将this.state.totalprice 全部改为this.props.price
将purchasable直接传入BuildControl,不经过setstate;

import React, { Component } from 'react';

import Aux from '../../hoc/_Aux/_Aux';
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';
import Spinner from '../../components/UI/Spinner/Spinner';
import withErrorHandler from '../../hoc/withErrorHandler/withErrorHandler';
import axios from '../../axios-orders';

import {connect} from 'react-redux';
import * as actionType from '../../store/actions';

class BurgerBuilder extends Component {
    state = {
        purchasing: false,
        loading: false,
        error: false
    }

    componentDidMount () {   //用于从database抓取初始ingredient
        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 = () => {
        const queryParams= [];
        for(let i in this.props.ings){
            queryParams.push(encodeURIComponent(i)+'='+encodeURIComponent(this.props.ings[i]));           //将code转为可用在url的形式
        };
        queryParams.push('price='+this.props.price);
        const queryString = queryParams.join('&');
        this.props.history.push({
            pathname:'/checkout',
            search: '?'+queryString
        });
    }

    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 = (
                <Aux>
                    <Burger ingredients={this.props.ings} />
                    <BuildControls
                        ingredientAdded={this.props.onIngredientAdded}
                        ingredientRemoved={this.props.onIngredientRemoved}
                        disabled={disabledInfo}
                        purchasable={this.updatePurchaseState(this.props.ings)} //传入ings
                        ordered={this.purchaseHandler}
                        price={this.props.price} />
                </Aux>
            );
            orderSummary = <OrderSummary
                ingredients={this.props.ings}
                price={this.props.price}
                purchaseCancelled={this.purchaseCancelHandler}
                purchaseContinued={this.purchaseContinueHandler} />;
        }
        if ( this.state.loading ) {
            orderSummary = <Spinner />;
        }
        // {salad: true, meat: false, ...}
        return (
            <Aux>
                <Modal show={this.state.purchasing} modalClosed={this.purchaseCancelHandler}>
                    {orderSummary}
                </Modal>
                {burger}
            </Aux>
        );
    }
}

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

const mapDispatchToProps=dispatch=>{
    return{
        onIngredientAdded:(ingName)=>dispatch({type:actionType.ADD_INGREDIENTS,ingredientName:ingName}),
        onIngredientRemoved:(ingName)=>dispatch({type:actionType.REMOVE_INGREDIENTS,ingredientName:ingName})
    };
};

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

在checkout中用redux代替query的传递

BurgerBuilder.js中无需设置复杂的route
continue直接进入简单的checkout即可;

    purchaseContinueHandler = () => {
        this.props.history.push('/checkout');
    }

checkout.js
route无需向下传入query数据,直接进入contact-data,传入component即可;

import React , {Component} from 'react';
import CheckoutSummary from '../../components/order/CheckoutSummary/CheckoutSummary';
import {Route} from 'react-router-dom';
import ContactData from '../ContactData/ContactData';

import {connect} from 'react-redux';
class Checkout extends Component{

    checkoutCancelledHandler=()=>{
        this.props.history.goBack();
    }

    checkoutContinuedHandler=()=>{
        this.props.history.replace(this.props.match.url+'/contact-data');
    }

    render(){
        return(
            <div>
                <CheckoutSummary 
                    ingredients={this.props.ings}
                    checkoutCancelled={this.checkoutCancelledHandler}
                    checkoutContinued={this.checkoutContinuedHandler}/>
                <Route 
                    path={this.props.match.path + '/contact-data'} 
                    component={ContactData}
                    />
            </div>
        );
    }
};

const mapStateToProps =state=>{
    return{
        ings: state.ingredients
    }
};

export default connect(mapStateToProps)(Checkout);

在contactData中需要用到price和ingredients,无需从checkout中接收
由redux传入,调用即可;
省去蛮烦的query传递;

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

export default connect(mapStateToProps)(ContactData);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值