Sunday, October 30, 2022

React Context: use context instead of passing data with usestate to nested components

Readme


1. create Cart-Context.js with default structure (ie, **{items:[],totalAmount:0,addItem:(item)=>{},removeItem:(id)=>{}}**)

2. create CartProvider.js with above Cart-Context default obj structure,using it with dynamic values 

{ items:[],totalAmount:0, addItem:addItemToCartHandler,removeItem:removeItemFromCartHandler },

ii.Create reducer and dispatch data from functions with addItemToCartHandler, removeItemFromCartHandler

iii.create usestate and add reducer to usestate

iv.<CartContext.Provider value={cartContext}> {props.children} </CartContext.Provider>

3.In app.js <CartProvider>  <Header onShowCart={showCartHandler}/>... </CartProvider>

4.In header.js <header className={classes.header}><HeaderCartButton onClick={props.onShowCart}></HeaderCartButton></header>

5.HeaderCartButton.js :


const HeaderCartButton = (props) => {

    const cartCtx= useContext(CartContext);

    const numberOfCartItems= cartCtx.items.reduce((curNumber, item)=>{

        return curNumber+item.amount;

    },0);

  return (

    <Fragment>

      <button className={classes.button} onClick={props.onClick}>

        {/* 3. for popopening */}

        <span className={classes.icon}>

          <CartIcon/>

        </span>

        <span>Cart</span>

        <span className={classes.badge}>{numberOfCartItems}</span>

      </button>

    </Fragment>

  );

};

_________________________________________________________


Cart-Context.js

import React from "react";

const CartContext=React.createContext({
    items:[],
    totalAmount:0,
    addItem:(item)=>{},
    removeItem:(id)=>{}
});

export default CartContext


2.CartProvider.js

import { useReducer } from "react";
import CartContext  from "./cart-context";
const defaultCartState={
    items:[],
    totalAmount:0
};
const cartReducer=(state,action)=>{
    if(action.type="ADD"){
    const updatedItems= state.items.concat(action.item);
    const updatedTotalAmount=state.totalAmount+action.item.price*action.item.amount;
    return {
        items:updatedItems,
        totalAmount:updatedTotalAmount
    };
    }else if(action.type="REMOVE"){

    }
   return defaultCartState;
}
const CartProvider= props=>{
   const [cartstate, dispatchCartAction]= useReducer(cartReducer,defaultCartState);
    const addItemToCartHandler=(item)=>{
        dispatchCartAction({type:'ADD',item:item});
    }
    const removeItemFromCartHandler=(id)=>{
    dispatchCartAction({type:"REMOVE",id:id})
    }
    const cartContext={ // first add these below lines next write reducer code.
        // items:[],totalAmount:0, initially like this b4 adding reducer
        items:cartstate.items,
        totalAmount:cartstate.totalAmount,
        addItem:addItemToCartHandler,
        removeItem:removeItemFromCartHandler
    };
    return <CartContext.Provider value={cartContext}>
       {props.children}
    </CartContext.Provider>
}

export default CartProvider;

3.App.js

 return (
    <CartProvider>
      {cartIsShown && <Cart onClose={hideCartHandler}/>}
      <Header onShowCart={showCartHandler}/>
       {/* 1. for popopening */}
      <main>
        <Meals />
      </main>
    </CartProvider>
  );
}

export default App;
4.Header.js 

import React, { Fragment } from "react";
import HeaderCartButton from "./HeaderCartButton";
import classes from './Header.module.css';
import mealsImage from '../../assets/meals.jpg'
const Header = (props)=>{
    return <Fragment>
        <header className={classes.header}>
        <h1>ReactMeals</h1>
        <HeaderCartButton onClick={props.onShowCart}></HeaderCartButton>
         {/* 2. for popopening */}
        </header>
        <div className={classes['main-image']}><img src={mealsImage}></img></div>
    </Fragment>
}
export default Header;

HeaderCartButton.js
import CartContext from "../../store/cart-context";


const HeaderCartButton = (props) => {
    const cartCtx= useContext(CartContext);
    const numberOfCartItems= cartCtx.items.reduce((curNumber, item)=>{
        return curNumber+item.amount;
    },0);
  return (
    <Fragment>
      <button className={classes.button} onClick={props.onClick}>
        {/* 3. for popopening */}
        <span className={classes.icon}>
          <CartIcon/>
        </span>
        <span>Cart</span>
        <span className={classes.badge}>{numberOfCartItems}</span>
      </button>
    </Fragment>
  );
};
export default HeaderCartButton;

No comments:

Post a Comment