Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from 'react';
- import ReactDOM from 'react-dom';
- import './index.css';
- const productsList = [
- {
- sku: "first_product",
- title: "Fishsticks",
- price: 8.99
- },
- {
- sku: "second_product",
- title: "Pineapple Pen",
- price: 3.99
- },
- {
- sku: "third_product",
- title: "Krabby Patty Secret Formula",
- price: 19.99
- }
- ];
- // createReducer function
- const createReducer = products => {
- return (state, action) => {
- const prodList = products;
- switch (action.type) {
- case "ADD_TO_CART":
- // determine if valid product
- if (prodList.find(product => product.sku === action.payload.sku)) {
- let newState1 = [...state];
- // increment cart item quantity if exists
- if (newState1.find(item => item.product.sku === action.payload.sku)) {
- window.console.log(`Increment ${action.payload.sku} fired`);
- ++newState1.find(item => item.product.sku === action.payload.sku)
- .quantity;
- } else {
- window.console.log(`Pushed ${action.payload.sku} product onto cart.`);
- newState1.push({
- quantity: 1,
- product: prodList.find(
- product => product.sku === action.payload.sku
- )
- });
- }
- return newState1;
- }
- // if not valid product return previous state
- return state;
- case "SUBTRACT_FROM_CART":
- let newState2 = [...state];
- // determine if product exists
- if (newState2.find(item => item.product.sku === action.payload.sku)) {
- // retrieve item
- const item = state.find(
- item => item.product.sku === action.payload.sku
- );
- // if quantity is less than 2 remove
- if (item.quantity < 2) {
- window.console.log(`Pop ${action.payload.sku} from cart.`);
- newState2 = newState2.filter(
- cartItem => cartItem.product.sku != item.product.sku
- );
- } else {
- window.console.log(`Decrement ${action.payload.sku}`);
- --newState2.find(item => item.product.sku === action.payload.sku)
- .quantity;
- }
- return newState2;
- }
- // if not valid product return previous state
- return state;
- case "DELETE_FROM_CART":
- let newState3 = state.filter(
- item => item.product.sku != action.payload.sku
- );
- return newState3;
- default:
- return state;
- }
- };
- };
- // create Context & Provider
- /*
- const Context = React.createContext();
- const Provider = props => {
- const [state, dispatch] = React.useReducer(createReducer(productsList), []);
- return (
- <Context.Provider value={{ state, dispatch }}>
- {props.children}
- </Context.Provider>
- );
- }
- */
- // useCallbackでメモ化させる
- // reducer による再レンダリングを防ぐ
- const Context = React.createContext();
- const Provider = props => {
- const memoizedReducer = React.useCallback(createReducer(productsList), [productsList])
- const [state, dispatch] = React.useReducer(memoizedReducer, []);
- return (
- <Context.Provider value={{ state, dispatch }}>
- {props.children}
- </Context.Provider>
- );
- }
- // display component
- const Display = () => {
- const cartContext = React.useContext(Context);
- const [hidden, setHidden] = React.useState(false);
- return (
- <div>
- <button onClick={e => {
- e.preventDefault();
- setHidden(hidden ? false : true);
- }}
- >Toggle z-index</button>
- <div
- style={{ backgroundColor: "palevioletred", display: hidden ? "none" : "block" }}
- >
- <h1 style={{ margin: "0" }}>These button should dispatch the "ADD_TO_CART" action.</h1>
- <p>Observe console print statements on initial clicks.</p>
- <div style={{ padding: "20px", display: "flex", justifyContent: "center" }}>
- {productsList.map(product => (
- <div>
- <button
- onClick={e => {
- e.preventDefault();
- window.console.log(`${product.sku} ATC button pushed`);
- cartContext.dispatch({ type: "ADD_TO_CART", payload: { sku: product.sku } });
- }}
- >Add {product.title} to Cart</button>
- </div>
- ))}
- </div>
- </div>
- <div style={{ display: hidden ? "none" : "block" }}>
- {cartContext.state.map(item => (
- <div>
- <button onClick={e => {
- e.preventDefault();
- window.console.log(`${item.product.sku} INC button pushed`);
- cartContext.dispatch({ type: "ADD_TO_CART", payload: { sku: item.product.sku } });
- }}
- >Increment {item.product.title}</button>
- <p>{item.quantity}</p>
- <button onClick={e => {
- e.preventDefault();
- window.console.log(`${item.product.sku} DEC button pushed`);
- cartContext.dispatch({ type: "SUBTRACT_FROM_CART", payload: { sku: item.product.sku } });
- }}
- >Decrement {item.product.title}</button>
- </div>
- ))}
- </div>
- </div>
- );
- }
- ReactDOM.render(
- <Provider>
- <Display />
- </Provider>,
- document.getElementById("root")
- );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement