我知道有人问过类似的问题,但我找不到一个我可以适应我的代码的(可能是因为我仍然是Redux的新手). 因此,我正在编辑已经编写的购物车功能,其中我已经有两个函数:

  1. 每次用户添加或删除产品时更新数量号(S).
  2. 更新新增产品总价. 目前,数量数字是通过输入的默认箭头显示的(因此它不是非常touch 屏友好的),用户不能真正删除开始的数字1,以便通过键入"手动"更改数量. 我的工作是使增加和减少按钮与不同的输入,其中用户也将能够键入所需的数量.我怎么能这样做呢?
export function calculateTotal(cart) {
    let totalUSD = 0;
    Object.keys(cart).forEach((itemName) => {
      totalUSD += cart[itemName].price * cart[itemName].quantity;
    });
    return totalUSD.toFixed(2);
  }
  export function calculateTotal(cart) {
    let totalUSD = 0;
    Object.keys(cart).forEach((itemName) => {
      totalUSD += cart[itemName].price * cart[itemName].quantity;
    });
    return totalUSD.toFixed(2);
  }
  export function calculateTotalQuantity(cart) {
    let totalQuantity = 0;
    Object.keys(cart).forEach((itemName) => {
      totalQuantity += cart[itemName].quantity;
    });
    return totalQuantity;
  }
import React from 'react';
import "./Cart.css";
import Navbar from './Navbar.jsx';
import Footer from './Footer.jsx';
import { useDispatch, useSelector } from 'react-redux';
import { changeItemQuantity } from '../features/cart/cartSlice.js';
import { calculateTotal } from '../features/utilities/utilities.js';
import { removeAll } from '../features/cart/cartSlice.js';

export default function Cart() {

  const dispatch = useDispatch();
  const cart = useSelector(state => state.cart); // * Note
  const onInputChangeHandler = (name, input) => {
    // If the user enters a bad value...
    if (input === '') {
      return;
    }

    // Otherwise, convert the input into a number and pass it along as the newQuantity.
   const newQuantity = Number(input);

    dispatch(changeItemQuantity(name, newQuantity));

  };

  const onRemoveAll = () => {

    dispatch(removeAll());
  };
  // Use the cart and currencyFilter slices to render their data.
  const cartElements = Object.entries(cart).map(createCartItem);
  const total = calculateTotal(cart);
  
  return (
    <>
      <Navbar/>
      <div id="cart-container">
        <ul id="cart-items">
          {cartElements == '' ? <div className="cart-empty">Your cart is empty</div> : cartElements}
        </ul>
        <div className="price-btn-container">
          {cartElements.length > 0 ? <button
              onClick={() => onRemoveAll()}
              className="remove-all"
            >
              Remove All
            </button> : <div></div>}
          <h3 className="total">
            Total{' '}
            <span className="total-value">
              ${total} 
            </span>
          </h3>
        </div>
      </div>
      <Footer/>
    </>
  );

  function createCartItem([name, item]) {
    if (item.quantity === 0) {
      return;
    }

    return (
      <li className="cart-list" key={name}>
        <img src={item.img}/>
        <p>{name}</p>
        <p>{item.type}</p>
        <div className="quantity-container">
          <p>Quantity:</p>
          <input 
          type="number" 
          className="item-quantity" 
          name="quantity" 
          value={item.quantity}
          onChange={(e) => {
            onInputChangeHandler(name, e.target.value);
          }}/>
        </div>
      </li>
    );
  }
};
export const addItem = (itemToAdd) => {
    return {
      type: 'cart/addItem',
      payload: itemToAdd,
    };
  };

  export const removeAll = () => {
    return {
      type: 'cart/removeAll',
      payload: initialCart
    }

  }
  
  export const changeItemQuantity = (name, newQuantity ) => {
   return {
      type: 'cart/changeItemQuantity',
      payload: {
        name,
        newQuantity
      }
    }
  }
  
  
  const initialCart = [];
  export const cartReducer = (cart = initialCart, action) => {
    switch (action.type) {
      case 'cart/addItem': {
        const { name, price, img, type } = action.payload;
        
        // if the item already exists, increase the quantity by 1, otherwise set it to 1
        const quantity = cart[name] ? cart[name].quantity + 1 : 1;
        const newItem = { price, img, type, quantity };
  
        // Add the new item to the cart (or replace it if it existed already)
        return { 
          ...cart, 
          [name]: newItem 
        };
      }
      case 'cart/removeItem':
        return cart.filter(item => item !== action.payload);
        
      case 'cart/removeAll':
        return initialCart;

      case 'cart/changeItemQuantity': {
        const { name, newQuantity } = action.payload;
        const itemToUpdate = cart[name];
        const updatedItem = {
          ...itemToUpdate,
          quantity: newQuantity
        }
        // Create a copy of itemToUpdate and update the quantity prop.
        return {
          ...cart,
          [name]: updatedItem 
        }
      }
      default: {
        return cart;
      }
    }
  };

推荐答案

创建两个新的活动/减少器 case 以增加/减少条目数量.

export const addItem = (itemToAdd) => ({
  type: 'cart/addItem',
  payload: itemToAdd,
});

export const removeAll = () => ({
  type: 'cart/removeAll',
  payload: initialCart
});
  
export const changeItemQuantity = (name, newQuantity) => ({
  type: 'cart/changeItemQuantity',
  payload: { name, newQuantity }
});

export const const incrementItemQuantity = (name) => ({
  type: 'cart/incrementItemQuantity',
  payload: name
});

export const const decrementItemQuantity = (name) => ({
  type: 'cart/decrementItemQuantity',
  payload: name
});
  
const initialCart = {};

export const cartReducer = (cart = initialCart, action) => {
  switch (action.type) {
    case 'cart/addItem': {
      const { name, price, img, type } = action.payload;
        
      // if the item already exists, increase the quantity by 1, otherwise set it to 1
      const quantity = cart[name] ? cart[name].quantity + 1 : 1;
      const newItem = { price, img, type, quantity };
  
      // Add the new item to the cart (or replace it if it existed already)
      return { 
        ...cart, 
        [name]: newItem 
      };
    }

    case 'cart/removeItem':
      return cart.filter(item => item !== action.payload);
        
    case 'cart/removeAll':
      return initialCart;

    case 'cart/changeItemQuantity': {
      const { name, newQuantity } = action.payload;

      return {
        ...cart,
        [name]: {
          ...cart[name],
          quantity: newQuantity
        } 
      }
    }

    case 'cart/incrementItemQuantity':
      const name = action.payload;
      return {
        ...cart,
        [name]: {
          ...cart[name],
          quantity: cart[name].quantity + 1
        } 
      }

    case 'cart/decrementItemQuantity':
      const name = action.payload;
      return {
        ...cart,
        [name]: {
          ...cart[name],
          quantity: Math.max(1, cart[name].quantity - 1)
        } 
      }

    default:
      return cart;
  }
};
import React from 'react';
import "./Cart.css";
import Navbar from './Navbar.jsx';
import Footer from './Footer.jsx';
import { useDispatch, useSelector } from 'react-redux';
import {
  changeItemQuantity,
  decrementItemQuantity,
  incrementItemQuantity,
  removeAll
} from '../features/cart/cartSlice.js';
import { calculateTotal } from '../features/utilities/utilities.js';

export default function Cart() {
  const dispatch = useDispatch();
  const cart = useSelector(state => state.cart); // * Note

  const onInputChangeHandler = (name, input) => {
    // If the user enters a bad value...
    if (input === '') {
      return;
    }

    // Otherwise, convert the input into a number and pass it along as the newQuantity.
    const newQuantity = Number(input);

    dispatch(changeItemQuantity(name, newQuantity));
  };

  const onRemoveAll = () => dispatch(removeAll());
  const incrementItem = (name) => dispatch(incrementItemQuantity(name));
  const decrementItem = (name) => dispatch(decrementItemQuantity(name));

  function createCartItem([name, item]) {
    return (
      <li className="cart-list" key={name}>
        <img src={item.img}/>
        <p>{name}</p>
        <p>{item.type}</p>
        <div className="quantity-container">
          <p>Quantity:</p>
          <input 
            type="number" 
            className="item-quantity" 
            name="quantity" 
            value={item.quantity}
            onChange={(e) => {
              onInputChangeHandler(name, e.target.value);
            }}
          />
          <button type="button" onClick={decrementItem.bind(null, name)}>
            -
          </button>
          <button type="button" onClick={incrementItem.bind(null, name)}>
            +
          </button>
        </div>
      </li>
    );
  }
  
  // Use the cart and currencyFilter slices to render their data.
  const cartElements = Object.entries(cart)
    .filter(([,item]) => item.quantity)
    .map(createCartItem);

  const total = calculateTotal(cart);

  return (
    <>
      <Navbar />
      <div id="cart-container">
        {cartElements.length
          ? (
            <ul id="cart-items">
              {cartElements}
            </ul>
          ) : <div className="cart-empty">Your cart is empty</div>
        }
        <div className="price-btn-container">
          {!!cartElements.length && ( // <-- coerce length to boolean
            <button
              onClick={onRemoveAll}
              className="remove-all"
            >
              Remove All
            </button>
          )}
          <h3 className="total">
            Total{' '}
            <span className="total-value">
              ${total} 
            </span>
          </h3>
        </div>
      </div>
      <Footer />
    </>
  );
};

如果你不想要额外的动作/减量,你可以用changeItemQuantity动作来处理.

case 'cart/changeItemQuantity': {
  const { name, newQuantity } = action.payload;

  return {
    ...cart,
    [name]: {
      ...cart[name],
      quantity: Math.max(1, newQuantity),
    } 
  }
}
import React from 'react';
import "./Cart.css";
import Navbar from './Navbar.jsx';
import Footer from './Footer.jsx';
import { useDispatch, useSelector } from 'react-redux';
import {
  changeItemQuantity,
  removeAll
} from '../features/cart/cartSlice.js';
import { calculateTotal } from '../features/utilities/utilities.js';

export default function Cart() {
  const dispatch = useDispatch();
  const cart = useSelector(state => state.cart); // * Note

  const onInputChangeHandler = (name, input) => {
    // If the user enters a bad value...
    if (input === '') {
      return;
    }

    // Otherwise, convert the input into a number and pass it along as the newQuantity.
    const newQuantity = Number(input);

    dispatch(changeItemQuantity(name, newQuantity));
  };

  const onRemoveAll = () => dispatch(removeAll());
  const incrementItem = (name, item) => dispatch(
    changeItemQuantity(name, item.quantity + 1)
  );
  const decrementItem = (name, item) => dispatch(
    changeItemQuantity(name, item.quantity - 1)
  );

  function createCartItem([name, item]) {
    return (
      <li className="cart-list" key={name}>
        <img src={item.img}/>
        <p>{name}</p>
        <p>{item.type}</p>
        <div className="quantity-container">
          <p>Quantity:</p>
          <input 
            type="number" 
            className="item-quantity" 
            name="quantity" 
            value={item.quantity}
            onChange={(e) => {
              onInputChangeHandler(name, e.target.value);
            }}
          />
          <button type="button" onClick={decrementItem.bind(null, name, item)}>
            -
          </button>
          <button type="button" onClick={incrementItem.bind(null, name, item)}>
            +
          </button>
        </div>
      </li>
    );
  }
  
  // Use the cart and currencyFilter slices to render their data.
  const cartElements = Object.entries(cart)
    .filter(([,item]) => item.quantity)
    .map(createCartItem);

  const total = calculateTotal(cart);

  return (
    <>
      <Navbar />
      <div id="cart-container">
        {cartElements.length
          ? (
            <ul id="cart-items">
              {cartElements}
            </ul>
          ) : <div className="cart-empty">Your cart is empty</div>
        }
        <div className="price-btn-container">
          {!!cartElements.length && (
            <button
              onClick={onRemoveAll}
              className="remove-all"
            >
              Remove All
            </button>
          )}
          <h3 className="total">
            Total{' '}
            <span className="total-value">
              ${total} 
            </span>
          </h3>
        </div>
      </div>
      <Footer />
    </>
  );
};

Javascript相关问答推荐

无法将nPM simplex-noise包导入在JS项目中工作

使用redux-toolet DelivercThunks刷新访问令牌

如何通过在提交时工作的函数显示dom元素?

*ngFor和@代表输入decorator 和选角闭合

拖放仅通过 Select 上传

在这种情况下,如何 for each 元素添加id?

给定一个凸多边形作为一组边,如何根据到最近边的距离填充里面的区域

为什么!逗号和空格不会作为输出返回,如果它在参数上?

使用LocaleCompare()进行排序时,首先使用大写字母

从Nextjs中的 Select 项收集值,但当单击以处理时,未发生任何情况

Use Location位置成员在HashRouter内为空

自定义图表工具提示以仅显示Y值

Google脚本数组映射函数横向输出

打字脚本中方括号符号属性访问和拾取实用程序的区别

使用自动识别发出信号(&Q)

P5.js中的分形树

我怎样才能得到一个数组的名字在另一个数组?

需要RTK-在ReactJS中查询多个组件的Mutations 数据

将字符串解释为数字;将其重新编码为另一个基数

如何将值从后端传递到前端