当前位置: 首页 > article >正文

React 第三十节 使用 useState 和 useEffect Hook实现购物车

不使用 redux 实现 购物车案例

使用 React 自带的 useState 和 useEffect Hook 即可实现购物车

export default function ShoppingCar() {// 要结算的商品 总数 以及总价const [totalNum, setTotalNum] = useState(0)const [totalPerice, setTotalPerice] = useState(0)// 商品列表 初始化一个mock 数据const [list, setList] = useState(orderLists)...
}

1、新增商品

使用 setList() 进数据状态更新

// 模拟新增商品
const handleAdd = () => {const curList = [...list]console.log('===curList=', curList)curList.unshift({name: `商品${list.length + 1}`,id: `sss_${list.length + 1}` ,num: 1,price: 12.00,totalPrice: 12.00, })setList([...curList])
}

2、修改商品的数量

const handleChangeNum = (type, id) => {const curList = [...list]if(type === 'ADD') {curList.map(itm => {if (itm.id === id) {itm.num = itm.num + 1itm.totalPrice = itm.num * itm.price}})} else{curList.map(itm => {if (itm.id === id) {itm.num = itm.num !== 0  ? itm.num - 1 : 0itm.totalPrice = itm.num * itm.price}})}setList([...curList])
}

3、选择要结算的商品

const handleChangeCheckbox = (e, id) =>{console.log('---', e.target.value)const curList = [...list]curList.map(itm => {if (itm.id === id) {itm.isChecked = !itm.isChecked}})setList([...curList])
}

4、计算要结算商品的 总数 及 总价

使用 useEffect() 监测 商品列表的变化

useEffect(() => {let isSelectedLists = []list.map(itm => {if (itm.isChecked) {isSelectedLists.push(itm)}})console.log('=isSelectedLists==', isSelectedLists)const curNum = isSelectedLists && isSelectedLists.length &&isSelectedLists.reduce((total, item) => total + item.num, 0) || 0const curTotal = isSelectedLists && isSelectedLists.length && isSelectedLists.reduce((total, item) => total + item.totalPrice, 0) || 0console.log('==curNum==', curNum)console.log('==curTotal==', curTotal)setTotalNum(curNum)setTotalPerice(curTotal)
}, [list]

5、完整代码案例

// index.jsx 
import React, {useState, useEffect, useId} from 'react'
import './index.scss'
import { orderLists } from './mock.js'
export default function ShoppingCar() {// const id = useId()const [totalNum, setTotalNum] = useState(0)const [totalPerice, setTotalPerice] = useState(0)const [list, setList] = useState(orderLists)const handleChangeNum = (type, id) => {const curList = [...list]if(type === 'ADD') {curList.map(itm => {if (itm.id === id) {itm.num = itm.num + 1itm.totalPrice = itm.num * itm.price}})} else{curList.map(itm => {if (itm.id === id) {itm.num = itm.num !== 0  ? itm.num - 1 : 0itm.totalPrice = itm.num * itm.price}})}setList([...curList])}const handleChangeCheckbox = (e, id) =>{console.log('---', e.target.value)const curList = [...list]curList.map(itm => {if (itm.id === id) {itm.isChecked = !itm.isChecked}})setList([...curList])}const handleAdd = () => {const curList = [...list]console.log('===curList=', curList)curList.unshift({name: `商品${list.length + 1}`,id: `sss_${list.length + 1}` ,num: 1,price: 12.00,totalPrice: 12.00, })setList([...curList])}useEffect(() => {let isSelectedLists = []list.map(itm => {if (itm.isChecked) {isSelectedLists.push(itm)}})console.log('=isSelectedLists==', isSelectedLists)const curNum = isSelectedLists && isSelectedLists.length &&isSelectedLists.reduce((total, item) => total + item.num, 0) || 0const curTotal = isSelectedLists && isSelectedLists.length && isSelectedLists.reduce((total, item) => total + item.totalPrice, 0) || 0console.log('==curNum==', curNum)console.log('==curTotal==', curTotal)setTotalNum(curNum)setTotalPerice(curTotal)}, [list])return (<div className='list'>{list.map(itm => {return (<div className="li" key={itm.id}><div className='commodity'><input type="checkbox" name="" id="" value={itm.isChecked} onClick={(e) => handleChangeCheckbox(e, itm.id)}/><span>{itm.name}</span></div><div className="price">单价:{itm.price}</div><div className='num'><span className='handle-icon' onClick={() => handleChangeNum('ADD', itm.id)}>+</span><span className='itm-num'>{itm.num}</span><span  className='handle-icon' onClick={() => handleChangeNum('REDUCE', itm.id)}>-</span></div><div className='total'>总价:{itm.totalPrice}</div></div>)})}<div className='total'><span className='total-num'>共计:{totalNum}</span><span className='total-price'>合计:{totalPerice}</span></div><button className="btn" onClick={handleAdd}>增加商品</button></div>)
}
// index.scss 文件
.li{width: 100%;height: auto;display: flex;align-items: left;justify-content: left;
}
.commodity{width: 100%;height: 46px;display: flex;align-items: center;justify-content: left;&>span{display: inline-block;min-width: 100px;margin-left: 6px;margin-right: 6px;}}
.price{display: inline-block;margin-left: 6px;margin-right: 6px;min-width: 90px;
}
.num{width: 100%;height: 36px;display: flex;align-items: center;cursor: pointer;
}
.handle-icon{display: inline-block;width: 36px;height: 36px;cursor: pointer;line-height: 36px;border: 1px solid #efefef;
}
.itm-num{display: inline-block;padding: 2px 8px;
}
.total{min-width: 100px;color: #ff0000;
}
.total-price{margin-left: 20px;
}
.btn{}

6、注意事项

a、使用useStatesetXXX() 函数进行修改 对象类型时候,需要修改其指针和值如果不修改指向,不会触发视图更新
b、列表中每一项需要有唯一性的key,这样才会触发唯一性进行数据更新;
c、使用useState 和 useEffect 实现的购物车,只能在当前页使用,不利于代码复用,并且会随着 购物车里面优惠券、折扣等逻辑的增加,而变的难以维护;

相关文章:

React 第三十节 使用 useState 和 useEffect Hook实现购物车

不使用 redux 实现 购物车案例 使用 React 自带的 useState 和 useEffect Hook 即可实现购物车 export default function ShoppingCar() {// 要结算的商品 总数 以及总价const [totalNum, setTotalNum] useState(0)const [totalPerice, setTotalPerice] useState(0)// 商品…...

Git的简介和简单的命令使用介绍

Git 是一种分布式版本控制系统&#xff0c;常用于跟踪文件的变化&#xff0c;协作开发和管理代码版本。以下是 Git 的基本概念和使用方式&#xff1a; 仓库&#xff08;Repository&#xff09;&#xff1a;Git 仓库是用来存储项目文件和版本历史的地方。可以通过在本地或远程创…...

概念辨析:Redis 多路 I/O 复用和多线程

Redis 多路 I/O 复用是在 Redis 2.0 引入的&#xff0c;而 Redis 多线程是在 Redis 6.0 引入的&#xff0c;两者不是同一个概念。 多路复用的本质还是同步 I/O&#xff0c;因为最终都需要主线程调用 read() 方法把数据拷贝到用户态。 在并发量非常大的情况下&#xff0c;Redi…...

海洋大地测量基准与水下导航系列之八我国海洋水下定位装备发展现状

中国国家综合PNT体系建设重点可概括为“51N”&#xff0c;“5”指5大基础设施&#xff0c;包括重点推进下一代北斗卫星导航系统、积极发展低轨导航增强系统、按需发展水下导航系统、大力发展惯性导航系统、积极探索脉冲星导航系统&#xff1b;“1”是实现1个融合发展&#xff0…...

计算机系统设计中的一些常用方法

面试中经常被问到&#xff1a; 有一个亿qq号&#xff0c;找出重复的 给你512m内存&#xff0c;找出5g文件中最大的数字 订单超时实现精准关单 … 当然&#xff0c;还有经常遇到的问题&#xff1a; 接口业务逻辑复杂或查数据库慢&#xff0c;相应耗时高 网络因为丢包导致服…...

【征程 6】工具链 VP 示例中 Cmakelists 解读

1. 引言 在文章【征程 6】VP 简介与单算子实操中&#xff0c;介绍了 VP 是什么&#xff0c;并以单算子 rotate 为例&#xff0c;介绍了 VP API 使用方法。在【征程 6】工具链 VP 示例中日志打印解读 中介绍了 VP 单算子示例中用到的日志打印的头文件应该怎么写。接下来和大家一…...

深入解析 Jenkins Agent 的 .jnlp 启动文件

&#x1f9e9; 深入解析 Jenkins Agent 的 .jnlp 启动文件 在 Jenkins 中&#xff0c;通过 JNLP&#xff08;Java Network Launch Protocol&#xff09;方式连接 Agent 是一种常见且灵活的方式。你可能曾见过类似这样的命令&#xff1a; java -jar agent.jar -jnlpUrl file:/…...

谷歌开源代理开发工具包(Agent Development Kit,ADK):让多智能体应用的构建变得更简

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

0x01、Redis 主从复制的实现原理是什么?

Redis 主从复制概述 Redis 的主从复制是一种机制&#xff0c;允许一个主节点&#xff08;主实例&#xff09;将数据复制到一个或多个从节点&#xff08;从实例&#xff09;。通过这一机制&#xff0c;从节点可以获取主节点的数据并与之保持同步。 复制流程 开始同步&#xf…...

noscript 标签是干什么的

vue public目录下的 index.html 会有 <noscript> 标签不知道是干吗的。 其实 noscript 标签在不支持或是禁用JavaScript 的浏览器中显示替代的内容。这个元素可以包含任何 HTML 元素。这个标签的用法也非常简单&#xff1a; <noscript><strong>Were sorry …...

[创业之路-366]:投资尽职调查 - 尽调核心逻辑与核心影响因素:价值、估值、退出、风险、策略

目录 一、VC投资的本质是冒着不确定性风险进行买卖、生意&#xff0c;为了赚取高额回报 1、VC投资的核心本质 2、VC投资的运作机制 3、VC投资的风险与挑战 4、VC投资的底层逻辑 5、总结&#xff1a;VC投资的本质再定义 二、尽调核心逻辑 1、尽调的含义 2、尽调的逻辑方…...

MOP数据库中的EXPLAIN用法

EXPLAIN 是 SQL 中的一个非常有用的工具&#xff0c;主要用于分析查询语句的执行计划。执行计划能展示数据库在执行查询时的具体操作步骤&#xff0c;像表的读取顺序、使用的索引情况、数据的访问方式等&#xff0c;这有助于我们对查询性能进行优化。 语法 不同的数据库系统&…...

Hyprnote开源程序是一款记录和转录您会议的 AI 记事本。 本地优先且可扩展 。

一、软件介绍 文末提供源码下载学习 Hyprnote开源程序是一款记录和转录您会议的 AI 记事本。 从您的原始会议记录中生成强大的摘要&#xff0c;本地优先且可扩展 。使用开源模型 &#xff08;Whisper & Llama&#xff09; 离线工作&#xff0c;高度可扩展 &#xff0c;由插…...

MSCKF及可观性总结

可观性 参考链接 真实VIO系统不能观的维度是4&#xff08;位置和yaw角&#xff09;&#xff0c;由于EKF的转移和观测Jacobian矩阵的线性化点不同、不可观方向噪声的存在&#xff0c;实际MSCKF不能观的维度变成了3&#xff0c;绕重力轴的旋转&#xff08;yaw角&#xff09;被错…...

上篇:新能源轻卡城配物流经济/动力模式量化定义(理论篇)——数学暴力破解工程困局

副标题&#xff1a;用微分方程撕开模式切换本质&#xff0c;用传感器数据重构载重真相 引言&#xff1a;为什么轻卡模式定义比乘用车难10倍&#xff1f; 行业现状痛点&#xff1a; 中国新能源轻卡日均载重波动高达300%&#xff08;空载0kg→满载4.5吨&#xff09;某头部车企实…...

Ubuntu22环境下,Docker部署阿里FunASR的gpu版本

番外: 随着deepseek的爆火,人工智能相关的开发变得异常火爆,相关的大模型开发很常见的agent智能体需要ASR语音识别的功能,阿里开源的FunASR几乎是把一个商业的项目放给我们使用了。那么我们项目中的生产环境怎么部署gpu版本的语音识别服务呢?经过跟deepseek的一上午的极限…...

Python 实现最小插件框架

文章目录 Python 实现最小插件框架1. 基础实现项目结构plugin_base.py - 插件基类plugins/hello.py - 示例插件1plugins/goodbye.py - 示例插件2main.py - 主程序 2. 更高级的特性扩展2.1 插件配置支持2.2 插件依赖管理2.3 插件热加载 3. 使用 setuptools 的入口点发现插件3.1 …...

内网邮箱服务器搭建-详解

目录 一、背景 二、搭建邮箱需要具备的基础知识 1、smtp&#xff08;Simple Mail Transfer Protocol&#xff09; SMTP工作原理 SMTP 命令 SMTP 协议端口 2、pop3&#xff08;Post Office Protocol&#xff09; POP3特点 POP3工作原理 3、imap4&#xff08;Internet M…...

21 天 Python 计划:使用SQLAlchemy 中的ORM查询

文章目录 准备工作图书表 books分类表 categoriesORM 对象定义 一、根据主键获取记录二、AND 查询三、 常用方法四、OR 查询五、 5. AND 和 OR 并存的查询六、巧用列表或者字典的解包给查询方法传参七、其它常用运算符八、查询指定列九、内连接、外连接9.1 内连接9.2 外连接9.3…...

使用 LLaMA-Factory 微调 llama3 模型(二)

使用 LLaMA-Factory 微调 llama3 模型 1. LLaMA-Factory模型介绍 https://github.com/hiyouga/LLaMA-FactoryLLaMA-Factory 是一个用于大型语言模型&#xff08;LLM&#xff09;微调的工具&#xff0c;它旨在简化大型语言模型的微调过程&#xff0c; 使得用户可以快速地对模型…...

并发编程--条件量与死锁及其解决方案

并发编程–条件量与死锁及其解决方案 文章目录 并发编程--条件量与死锁及其解决方案1.条件量1.1条件量基本概念1.2条件量的使用 2. 死锁 1.条件量 1.1条件量基本概念 在许多场合中&#xff0c;程序的执行通常需要满足一定的条件&#xff0c;条件不成熟的时候&#xff0c;任务…...

JAVA SE 自我总结

目录 1. 字面常量 2. 数据类型 3. 变量 4. 类型转换 5. 实参和形参的关系 6. 数组 6.1 数组的概念 6.2 动态初始化 6.3 静态初始化 7. 数据区 ​编辑 8. 数组的拷贝 8.1 赋值拷贝 8.2 方法拷贝 9. 代码块 10. 内部类 10.1 实例内部类 10.2 静态内部类 10.3 …...

RAG创建向量数据库:docsearch = FAISS.from_texts(documents, embeddings)

RAG创建向量数据库:docsearch = FAISS.from_texts(documents, embeddings) 代码解释 docsearch = FAISS.from_texts(documents, embeddings) 这行代码主要作用是基于给定的文本集合创建一个向量数据库(这里使用 FAISS 作为向量数据库工具 )。具体说明如下: FAISS :FAISS …...

虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解?

虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解&#xff1f; code review! 文章目录 虚幻引擎5-Unreal Engine笔记之“将MyStudent变量设置为一个BP_Student的实例”这句话如何理解&#xff1f;理解这句话的关键点1.类&#xff08…...

鸢尾花分类的6种机器学习方法综合分析与实现

鸢尾花分类的6种机器学习方法综合分析与实现 首先我们来看一下对应的实验结果。 数据准备与环境配置 在开始机器学习项目前&#xff0c;首先需要准备编程环境和加载数据。以下代码导入必要的库并加载鸢尾花数据集&#xff1a; import numpy as np import pandas as pd impo…...

vite,Vue3,ts项目关于axios配置

一、安装依赖包 npm install axios -S npm install qs -S npm install js-cookie 文件目录 二、配置线上、本地环境 与src文件同级,分别创建本地环境文件 .env.development 和线上环境文件 .env.production # 本地环境 ENV = development # 本地环境接口地址 VITE_API_URL =…...

mysql:重置表自增字段序号

情况一&#xff1a;清空表数据后重置自增 ID 如果你希望清空表中的所有数据&#xff0c;并将自增 ID 重置为初始值&#xff08;通常为 1&#xff09; 1、truncate truncate table tb_dict; 2、delete 配合 alter 语句 delete from tb_dict; alter table tb_dict AUTO_INCR…...

STM32 模块化开发指南 · 第 4 篇 用状态机管理 BLE 应用逻辑:分层解耦的实践方式

本文是《STM32 模块化开发实战指南》第 4 篇,聚焦于 BLE 模块中的状态管理问题。我们将介绍如何通过有限状态机(Finite State Machine, FSM)架构,实现 BLE 广播、扫描、连接等行为的解耦与可控,并配合事件队列驱动完成主从共存、低功耗友好、状态清晰的 BLE 应用。 一、为…...

HTML — 浮动

浮动 HTML浮动&#xff08;Float&#xff09;是一种CSS布局技术&#xff0c;通过float: left或float: right使元素脱离常规文档流并向左/右对齐&#xff0c;常用于图文混排或横向排列内容。浮动元素会紧贴父容器或相邻浮动元素的边缘&#xff0c;但脱离文档流后可能导致父容器高…...

IP节点详解及国内IP节点获取指南

获取国内IP节点通常涉及网络技术或数据资源的使用&#xff0c;IP地址作为网络设备的唯一标识&#xff0c;对于网络连接和通信至关重要。详细介绍几种修改网络IP地址的常用方法&#xff0c;无论是对于家庭用户还是企业用户&#xff0c;希望能找到适合自己的解决方案。以下是方法…...